linux-old/kernel/sys.c
<<
>>
Prefs
   1/*
   2 *  linux/kernel/sys.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 */
   6
   7#include <linux/errno.h>
   8#include <linux/sched.h>
   9#include <linux/kernel.h>
  10#include <linux/times.h>
  11#include <linux/utsname.h>
  12#include <linux/param.h>
  13#include <linux/resource.h>
  14#include <linux/signal.h>
  15#include <linux/string.h>
  16#include <linux/ptrace.h>
  17#include <linux/stat.h>
  18#include <linux/mman.h>
  19#include <linux/mm.h>
  20
  21#include <asm/segment.h>
  22#include <asm/io.h>
  23
  24/*
  25 * this indicates whether you can reboot with ctrl-alt-del: the default is yes
  26 */
  27static int C_A_D = 1;
  28
  29extern void adjust_clock(void);
  30
  31#define PZERO   15
  32
  33asmlinkage int sys_ni_syscall(void)
  34{
  35        return -ENOSYS;
  36}
  37
  38static int proc_sel(struct task_struct *p, int which, int who)
  39{
  40        switch (which) {
  41                case PRIO_PROCESS:
  42                        if (!who && p == current)
  43                                return 1;
  44                        return(p->pid == who);
  45                case PRIO_PGRP:
  46                        if (!who)
  47                                who = current->pgrp;
  48                        return(p->pgrp == who);
  49                case PRIO_USER:
  50                        if (!who)
  51                                who = current->uid;
  52                        return(p->uid == who);
  53        }
  54        return 0;
  55}
  56
  57asmlinkage int sys_setpriority(int which, int who, int niceval)
  58{
  59        struct task_struct **p;
  60        int error = ESRCH;
  61        int priority;
  62
  63        if (which > 2 || which < 0)
  64                return -EINVAL;
  65
  66        if ((priority = PZERO - niceval) <= 0)
  67                priority = 1;
  68
  69        for(p = &LAST_TASK; p > &FIRST_TASK; --p) {
  70                if (!*p || !proc_sel(*p, which, who))
  71                        continue;
  72                if ((*p)->uid != current->euid &&
  73                        (*p)->uid != current->uid && !suser()) {
  74                        error = EPERM;
  75                        continue;
  76                }
  77                if (error == ESRCH)
  78                        error = 0;
  79                if (priority > (*p)->priority && !suser())
  80                        error = EACCES;
  81                else
  82                        (*p)->priority = priority;
  83        }
  84        return -error;
  85}
  86
  87asmlinkage int sys_getpriority(int which, int who)
  88{
  89        struct task_struct **p;
  90        int max_prio = 0;
  91
  92        if (which > 2 || which < 0)
  93                return -EINVAL;
  94
  95        for(p = &LAST_TASK; p > &FIRST_TASK; --p) {
  96                if (!*p || !proc_sel(*p, which, who))
  97                        continue;
  98                if ((*p)->priority > max_prio)
  99                        max_prio = (*p)->priority;
 100        }
 101        return(max_prio ? max_prio : -ESRCH);
 102}
 103
 104asmlinkage int sys_profil(void)
 105{
 106        return -ENOSYS;
 107}
 108
 109asmlinkage int sys_ftime(void)
 110{
 111        return -ENOSYS;
 112}
 113
 114asmlinkage int sys_break(void)
 115{
 116        return -ENOSYS;
 117}
 118
 119asmlinkage int sys_stty(void)
 120{
 121        return -ENOSYS;
 122}
 123
 124asmlinkage int sys_gtty(void)
 125{
 126        return -ENOSYS;
 127}
 128
 129asmlinkage int sys_prof(void)
 130{
 131        return -ENOSYS;
 132}
 133
 134extern void hard_reset_now(void);
 135extern asmlinkage sys_kill(int, int);
 136
 137/*
 138 * Reboot system call: for obvious reasons only root may call it,
 139 * and even root needs to set up some magic numbers in the registers
 140 * so that some mistake won't make this reboot the whole machine.
 141 * You can also set the meaning of the ctrl-alt-del-key here.
 142 *
 143 * reboot doesn't sync: do that yourself before calling this.
 144 */
 145asmlinkage int sys_reboot(int magic, int magic_too, int flag)
 146{
 147        if (!suser())
 148                return -EPERM;
 149        if (magic != 0xfee1dead || magic_too != 672274793)
 150                return -EINVAL;
 151        if (flag == 0x01234567)
 152                hard_reset_now();
 153        else if (flag == 0x89ABCDEF)
 154                C_A_D = 1;
 155        else if (!flag)
 156                C_A_D = 0;
 157        else if (flag == 0xCDEF0123) {
 158                printk(KERN_EMERG "System halted\n");
 159                sys_kill(-1, SIGKILL);
 160                do_exit(0);
 161        } else
 162                return -EINVAL;
 163        return (0);
 164}
 165
 166/*
 167 * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
 168 * As it's called within an interrupt, it may NOT sync: the only choice
 169 * is whether to reboot at once, or just ignore the ctrl-alt-del.
 170 */
 171void ctrl_alt_del(void)
 172{
 173        if (C_A_D)
 174                hard_reset_now();
 175        else
 176                send_sig(SIGINT,task[1],1);
 177}
 178        
 179
 180/*
 181 * Unprivileged users may change the real gid to the effective gid
 182 * or vice versa.  (BSD-style)
 183 *
 184 * If you set the real gid at all, or set the effective gid to a value not
 185 * equal to the real gid, then the saved gid is set to the new effective gid.
 186 *
 187 * This makes it possible for a setgid program to completely drop its
 188 * privileges, which is often a useful assertion to make when you are doing
 189 * a security audit over a program.
 190 *
 191 * The general idea is that a program which uses just setregid() will be
 192 * 100% compatible with BSD.  A program which uses just setgid() will be
 193 * 100% compatible with POSIX w/ Saved ID's. 
 194 */
 195asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
 196{
 197        int old_rgid = current->gid;
 198        int old_egid = current->egid;
 199
 200        if (rgid != (gid_t) -1) {
 201                if ((old_rgid == rgid) ||
 202                    (current->egid==rgid) ||
 203                    suser())
 204                        current->gid = rgid;
 205                else
 206                        return(-EPERM);
 207        }
 208        if (egid != (gid_t) -1) {
 209                if ((old_rgid == egid) ||
 210                    (current->egid == egid) ||
 211                    (current->sgid == egid) ||
 212                    suser())
 213                        current->egid = egid;
 214                else {
 215                        current->gid = old_rgid;
 216                        return(-EPERM);
 217                }
 218        }
 219        if (rgid != (gid_t) -1 ||
 220            (egid != (gid_t) -1 && egid != old_rgid))
 221                current->sgid = current->egid;
 222        current->fsgid = current->egid;
 223        if (current->egid != old_egid)
 224                current->dumpable = 0;
 225        return 0;
 226}
 227
 228/*
 229 * setgid() is implemented like SysV w/ SAVED_IDS 
 230 */
 231asmlinkage int sys_setgid(gid_t gid)
 232{
 233        int old_egid = current->egid;
 234
 235        if (suser())
 236                current->gid = current->egid = current->sgid = current->fsgid = gid;
 237        else if ((gid == current->gid) || (gid == current->sgid))
 238                current->egid = current->fsgid = gid;
 239        else
 240                return -EPERM;
 241        if (current->egid != old_egid)
 242                current->dumpable = 0;
 243        return 0;
 244}
 245
 246asmlinkage int sys_acct(void)
 247{
 248        return -ENOSYS;
 249}
 250
 251asmlinkage int sys_phys(void)
 252{
 253        return -ENOSYS;
 254}
 255
 256asmlinkage int sys_lock(void)
 257{
 258        return -ENOSYS;
 259}
 260
 261asmlinkage int sys_mpx(void)
 262{
 263        return -ENOSYS;
 264}
 265
 266asmlinkage int sys_ulimit(void)
 267{
 268        return -ENOSYS;
 269}
 270
 271asmlinkage int sys_old_syscall(void)
 272{
 273        return -ENOSYS;
 274}
 275
 276/*
 277 * Unprivileged users may change the real uid to the effective uid
 278 * or vice versa.  (BSD-style)
 279 *
 280 * If you set the real uid at all, or set the effective uid to a value not
 281 * equal to the real uid, then the saved uid is set to the new effective uid.
 282 *
 283 * This makes it possible for a setuid program to completely drop its
 284 * privileges, which is often a useful assertion to make when you are doing
 285 * a security audit over a program.
 286 *
 287 * The general idea is that a program which uses just setreuid() will be
 288 * 100% compatible with BSD.  A program which uses just setuid() will be
 289 * 100% compatible with POSIX w/ Saved ID's. 
 290 */
 291asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
 292{
 293        int old_ruid = current->uid;
 294        int old_euid = current->euid;
 295
 296        if (ruid != (uid_t) -1) {
 297                if ((old_ruid == ruid) || 
 298                    (current->euid==ruid) ||
 299                    suser())
 300                        current->uid = ruid;
 301                else
 302                        return(-EPERM);
 303        }
 304        if (euid != (uid_t) -1) {
 305                if ((old_ruid == euid) ||
 306                    (current->euid == euid) ||
 307                    (current->suid == euid) ||
 308                    suser())
 309                        current->euid = euid;
 310                else {
 311                        current->uid = old_ruid;
 312                        return(-EPERM);
 313                }
 314        }
 315        if (ruid != (uid_t) -1 ||
 316            (euid != (uid_t) -1 && euid != old_ruid))
 317                current->suid = current->euid;
 318        current->fsuid = current->euid;
 319        if (current->euid != old_euid)
 320                current->dumpable = 0;
 321        return 0;
 322}
 323
 324/*
 325 * setuid() is implemented like SysV w/ SAVED_IDS 
 326 * 
 327 * Note that SAVED_ID's is deficient in that a setuid root program
 328 * like sendmail, for example, cannot set its uid to be a normal 
 329 * user and then switch back, because if you're root, setuid() sets
 330 * the saved uid too.  If you don't like this, blame the bright people
 331 * in the POSIX committee and/or USG.  Note that the BSD-style setreuid()
 332 * will allow a root program to temporarily drop privileges and be able to
 333 * regain them by swapping the real and effective uid.  
 334 */
 335asmlinkage int sys_setuid(uid_t uid)
 336{
 337        int old_euid = current->euid;
 338
 339        if (suser())
 340                current->uid = current->euid = current->suid = current->fsuid = uid;
 341        else if ((uid == current->uid) || (uid == current->suid))
 342                current->fsuid = current->euid = uid;
 343        else
 344                return -EPERM;
 345        if (current->euid != old_euid)
 346                current->dumpable = 0;
 347        return(0);
 348}
 349
 350/*
 351 * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
 352 * is used for "access()" and for the NFS daemon (letting nfsd stay at
 353 * whatever uid it wants to). It normally shadows "euid", except when
 354 * explicitly set by setfsuid() or for access..
 355 */
 356asmlinkage int sys_setfsuid(uid_t uid)
 357{
 358        int old_fsuid = current->fsuid;
 359
 360        if (uid == current->uid || uid == current->euid ||
 361            uid == current->suid || uid == current->fsuid || suser())
 362                current->fsuid = uid;
 363        if (current->fsuid != old_fsuid)
 364                current->dumpable = 0;
 365        return old_fsuid;
 366}
 367
 368/*
 369 * Samma på svenska..
 370 */
 371asmlinkage int sys_setfsgid(gid_t gid)
 372{
 373        int old_fsgid = current->fsgid;
 374
 375        if (gid == current->gid || gid == current->egid ||
 376            gid == current->sgid || gid == current->fsgid || suser())
 377                current->fsgid = gid;
 378        if (current->fsgid != old_fsgid)
 379                current->dumpable = 0;
 380        return old_fsgid;
 381}
 382
 383asmlinkage int sys_times(struct tms * tbuf)
 384{
 385        if (tbuf) {
 386                int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
 387                if (error)
 388                        return error;
 389                put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
 390                put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
 391                put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
 392                put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
 393        }
 394        return jiffies;
 395}
 396
 397asmlinkage int sys_brk(unsigned long brk)
 398{
 399        int freepages;
 400        unsigned long rlim;
 401        unsigned long newbrk, oldbrk;
 402
 403        if (brk < current->mm->end_code)
 404                return current->mm->brk;
 405        newbrk = PAGE_ALIGN(brk);
 406        oldbrk = PAGE_ALIGN(current->mm->brk);
 407        if (oldbrk == newbrk)
 408                return current->mm->brk = brk;
 409
 410        /*
 411         * Always allow shrinking brk
 412         */
 413        if (brk <= current->mm->brk) {
 414                current->mm->brk = brk;
 415                do_munmap(newbrk, oldbrk-newbrk);
 416                return brk;
 417        }
 418        /*
 419         * Check against rlimit and stack..
 420         */
 421        rlim = current->rlim[RLIMIT_DATA].rlim_cur;
 422        if (rlim >= RLIM_INFINITY)
 423                rlim = ~0;
 424        if (brk - current->mm->end_code > rlim ||
 425            brk >= current->mm->start_stack - 16384)
 426                return current->mm->brk;
 427        /*
 428         * Check against existing mmap mappings.
 429         */
 430        if (find_vma_intersection(current, oldbrk, newbrk))
 431                return current->mm->brk;
 432        /*
 433         * stupid algorithm to decide if we have enough memory: while
 434         * simple, it hopefully works in most obvious cases.. Easy to
 435         * fool it, but this should catch most mistakes.
 436         */
 437        freepages = buffermem >> 12;
 438        freepages += nr_free_pages;
 439        freepages += nr_swap_pages;
 440        freepages -= (high_memory - 0x100000) >> 16;
 441        freepages -= (newbrk-oldbrk) >> 12;
 442        if (freepages < 0)
 443                return current->mm->brk;
 444#if 0
 445        freepages += current->mm->rss;
 446        freepages -= oldbrk >> 12;
 447        if (freepages < 0)
 448                return current->mm->brk;
 449#endif
 450        /*
 451         * Ok, we have probably got enough memory - let it rip.
 452         */
 453        current->mm->brk = brk;
 454        do_mmap(NULL, oldbrk, newbrk-oldbrk,
 455                PROT_READ|PROT_WRITE|PROT_EXEC,
 456                MAP_FIXED|MAP_PRIVATE, 0);
 457        return brk;
 458}
 459
 460/*
 461 * This needs some heave checking ...
 462 * I just haven't get the stomach for it. I also don't fully
 463 * understand sessions/pgrp etc. Let somebody who does explain it.
 464 *
 465 * OK, I think I have the protection semantics right.... this is really
 466 * only important on a multi-user system anyway, to make sure one user
 467 * can't send a signal to a process owned by another.  -TYT, 12/12/91
 468 *
 469 * Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
 470 * LBT 04.03.94
 471 */
 472asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
 473{
 474        struct task_struct * p;
 475
 476        if (!pid)
 477                pid = current->pid;
 478        if (!pgid)
 479                pgid = pid;
 480        if (pgid < 0)
 481                return -EINVAL;
 482        for_each_task(p) {
 483                if (p->pid == pid)
 484                        goto found_task;
 485        }
 486        return -ESRCH;
 487
 488found_task:
 489        if (p->p_pptr == current || p->p_opptr == current) {
 490                if (p->session != current->session)
 491                        return -EPERM;
 492                if (p->did_exec)
 493                        return -EACCES;
 494        } else if (p != current)
 495                return -ESRCH;
 496        if (p->leader)
 497                return -EPERM;
 498        if (pgid != pid) {
 499                struct task_struct * tmp;
 500                for_each_task (tmp) {
 501                        if (tmp->pgrp == pgid &&
 502                         tmp->session == current->session)
 503                                goto ok_pgid;
 504                }
 505                return -EPERM;
 506        }
 507
 508ok_pgid:
 509        p->pgrp = pgid;
 510        return 0;
 511}
 512
 513asmlinkage int sys_getpgid(pid_t pid)
 514{
 515        struct task_struct * p;
 516
 517        if (!pid)
 518                return current->pgrp;
 519        for_each_task(p) {
 520                if (p->pid == pid)
 521                        return p->pgrp;
 522        }
 523        return -ESRCH;
 524}
 525
 526asmlinkage int sys_getpgrp(void)
 527{
 528        return current->pgrp;
 529}
 530
 531asmlinkage int sys_setsid(void)
 532{
 533        if (current->leader)
 534                return -EPERM;
 535        current->leader = 1;
 536        current->session = current->pgrp = current->pid;
 537        current->tty = NULL;
 538        current->tty_old_pgrp = 0;
 539        return current->pgrp;
 540}
 541
 542/*
 543 * Supplementary group ID's
 544 */
 545asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
 546{
 547        int i;
 548
 549        if (gidsetsize) {
 550                i = verify_area(VERIFY_WRITE, grouplist, sizeof(gid_t) * gidsetsize);
 551                if (i)
 552                        return i;
 553        }
 554        for (i = 0 ; (i < NGROUPS) && (current->groups[i] != NOGROUP) ; i++) {
 555                if (!gidsetsize)
 556                        continue;
 557                if (i >= gidsetsize)
 558                        break;
 559                put_fs_word(current->groups[i], (short *) grouplist);
 560                grouplist++;
 561        }
 562        return(i);
 563}
 564
 565asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
 566{
 567        int     i;
 568
 569        if (!suser())
 570                return -EPERM;
 571        if (gidsetsize > NGROUPS)
 572                return -EINVAL;
 573        for (i = 0; i < gidsetsize; i++, grouplist++) {
 574                current->groups[i] = get_fs_word((unsigned short *) grouplist);
 575        }
 576        if (i < NGROUPS)
 577                current->groups[i] = NOGROUP;
 578        return 0;
 579}
 580
 581int in_group_p(gid_t grp)
 582{
 583        int     i;
 584
 585        if (grp == current->fsgid)
 586                return 1;
 587
 588        for (i = 0; i < NGROUPS; i++) {
 589                if (current->groups[i] == NOGROUP)
 590                        break;
 591                if (current->groups[i] == grp)
 592                        return 1;
 593        }
 594        return 0;
 595}
 596
 597asmlinkage int sys_newuname(struct new_utsname * name)
 598{
 599        int error;
 600
 601        if (!name)
 602                return -EFAULT;
 603        error = verify_area(VERIFY_WRITE, name, sizeof *name);
 604        if (!error)
 605                memcpy_tofs(name,&system_utsname,sizeof *name);
 606        return error;
 607}
 608
 609asmlinkage int sys_uname(struct old_utsname * name)
 610{
 611        int error;
 612        if (!name)
 613                return -EFAULT;
 614        error = verify_area(VERIFY_WRITE, name,sizeof *name);
 615        if (error)
 616                return error;
 617        memcpy_tofs(&name->sysname,&system_utsname.sysname,
 618                sizeof (system_utsname.sysname));
 619        memcpy_tofs(&name->nodename,&system_utsname.nodename,
 620                sizeof (system_utsname.nodename));
 621        memcpy_tofs(&name->release,&system_utsname.release,
 622                sizeof (system_utsname.release));
 623        memcpy_tofs(&name->version,&system_utsname.version,
 624                sizeof (system_utsname.version));
 625        memcpy_tofs(&name->machine,&system_utsname.machine,
 626                sizeof (system_utsname.machine));
 627        return 0;
 628}
 629
 630asmlinkage int sys_olduname(struct oldold_utsname * name)
 631{
 632        int error;
 633        if (!name)
 634                return -EFAULT;
 635        error = verify_area(VERIFY_WRITE, name,sizeof *name);
 636        if (error)
 637                return error;
 638        memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
 639        put_fs_byte(0,name->sysname+__OLD_UTS_LEN);
 640        memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
 641        put_fs_byte(0,name->nodename+__OLD_UTS_LEN);
 642        memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN);
 643        put_fs_byte(0,name->release+__OLD_UTS_LEN);
 644        memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN);
 645        put_fs_byte(0,name->version+__OLD_UTS_LEN);
 646        memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
 647        put_fs_byte(0,name->machine+__OLD_UTS_LEN);
 648        return 0;
 649}
 650
 651/*
 652 * Only sethostname; gethostname can be implemented by calling uname()
 653 */
 654asmlinkage int sys_sethostname(char *name, int len)
 655{
 656        int     i;
 657        
 658        if (!suser())
 659                return -EPERM;
 660        if (len > __NEW_UTS_LEN)
 661                return -EINVAL;
 662        for (i=0; i < len; i++) {
 663                if ((system_utsname.nodename[i] = get_fs_byte(name+i)) == 0)
 664                        return 0;
 665        }
 666        system_utsname.nodename[i] = 0;
 667        return 0;
 668}
 669
 670/*
 671 * Only setdomainname; getdomainname can be implemented by calling
 672 * uname()
 673 */
 674asmlinkage int sys_setdomainname(char *name, int len)
 675{
 676        int     i;
 677        
 678        if (!suser())
 679                return -EPERM;
 680        if (len > __NEW_UTS_LEN)
 681                return -EINVAL;
 682        for (i=0; i < len; i++) {
 683                if ((system_utsname.domainname[i] = get_fs_byte(name+i)) == 0)
 684                        return 0;
 685        }
 686        system_utsname.domainname[i] = 0;
 687        return 0;
 688}
 689
 690asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
 691{
 692        int error;
 693
 694        if (resource >= RLIM_NLIMITS)
 695                return -EINVAL;
 696        error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
 697        if (error)
 698                return error;
 699        put_fs_long(current->rlim[resource].rlim_cur, 
 700                    (unsigned long *) rlim);
 701        put_fs_long(current->rlim[resource].rlim_max, 
 702                    ((unsigned long *) rlim)+1);
 703        return 0;       
 704}
 705
 706asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 707{
 708        struct rlimit new_rlim, *old_rlim;
 709        int err;
 710
 711        if (resource >= RLIM_NLIMITS)
 712                return -EINVAL;
 713        err = verify_area(VERIFY_READ, rlim, sizeof(*rlim));
 714        if (err)
 715                return err;
 716        memcpy_fromfs(&new_rlim, rlim, sizeof(*rlim));
 717        old_rlim = current->rlim + resource;
 718        if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
 719             (new_rlim.rlim_max > old_rlim->rlim_max)) &&
 720            !suser())
 721                return -EPERM;
 722        if (resource == RLIMIT_NOFILE) {
 723                if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
 724                        return -EPERM;
 725        }
 726        *old_rlim = new_rlim;
 727        return 0;
 728}
 729
 730/*
 731 * It would make sense to put struct rusage in the task_struct,
 732 * except that would make the task_struct be *really big*.  After
 733 * task_struct gets moved into malloc'ed memory, it would
 734 * make sense to do this.  It will make moving the rest of the information
 735 * a lot simpler!  (Which we're not doing right now because we're not
 736 * measuring them yet).
 737 */
 738int getrusage(struct task_struct *p, int who, struct rusage *ru)
 739{
 740        int error;
 741        struct rusage r;
 742
 743        error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
 744        if (error)
 745                return error;
 746        memset((char *) &r, 0, sizeof(r));
 747        switch (who) {
 748                case RUSAGE_SELF:
 749                        r.ru_utime.tv_sec = CT_TO_SECS(p->utime);
 750                        r.ru_utime.tv_usec = CT_TO_USECS(p->utime);
 751                        r.ru_stime.tv_sec = CT_TO_SECS(p->stime);
 752                        r.ru_stime.tv_usec = CT_TO_USECS(p->stime);
 753                        r.ru_minflt = p->mm->min_flt;
 754                        r.ru_majflt = p->mm->maj_flt;
 755                        break;
 756                case RUSAGE_CHILDREN:
 757                        r.ru_utime.tv_sec = CT_TO_SECS(p->cutime);
 758                        r.ru_utime.tv_usec = CT_TO_USECS(p->cutime);
 759                        r.ru_stime.tv_sec = CT_TO_SECS(p->cstime);
 760                        r.ru_stime.tv_usec = CT_TO_USECS(p->cstime);
 761                        r.ru_minflt = p->mm->cmin_flt;
 762                        r.ru_majflt = p->mm->cmaj_flt;
 763                        break;
 764                default:
 765                        r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime);
 766                        r.ru_utime.tv_usec = CT_TO_USECS(p->utime + p->cutime);
 767                        r.ru_stime.tv_sec = CT_TO_SECS(p->stime + p->cstime);
 768                        r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime);
 769                        r.ru_minflt = p->mm->min_flt + p->mm->cmin_flt;
 770                        r.ru_majflt = p->mm->maj_flt + p->mm->cmaj_flt;
 771                        break;
 772        }
 773        memcpy_tofs(ru, &r, sizeof(r));
 774        return 0;
 775}
 776
 777asmlinkage int sys_getrusage(int who, struct rusage *ru)
 778{
 779        if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
 780                return -EINVAL;
 781        return getrusage(current, who, ru);
 782}
 783
 784asmlinkage int sys_umask(int mask)
 785{
 786        int old = current->fs->umask;
 787
 788        current->fs->umask = mask & S_IRWXUGO;
 789        return (old);
 790}
 791
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.