Annotation of linux/kernel/sys.c, revision 1.1.1.4

1.1.1.2   root        1: /*
                      2:  *  linux/kernel/sys.c
                      3:  *
                      4:  *  (C) 1991  Linus Torvalds
                      5:  */
                      6: 
1.1       root        7: #include <errno.h>
                      8: 
                      9: #include <linux/sched.h>
                     10: #include <linux/tty.h>
                     11: #include <linux/kernel.h>
1.1.1.3   root       12: #include <linux/config.h>
1.1       root       13: #include <asm/segment.h>
                     14: #include <sys/times.h>
                     15: #include <sys/utsname.h>
1.1.1.3   root       16: #include <sys/param.h>
                     17: #include <sys/resource.h>
                     18: #include <string.h>
                     19: 
1.1.1.4 ! root       20: /*
        !            21:  * this indicates wether you can reboot with ctrl-alt-del: the deault is yes
        !            22:  */
        !            23: static int C_A_D = 1;
        !            24: 
1.1.1.3   root       25: /* 
                     26:  * The timezone where the local system is located.  Used as a default by some
                     27:  * programs who obtain this value by using gettimeofday.
                     28:  */
                     29: struct timezone sys_tz = { 0, 0};
                     30: 
                     31: extern int session_of_pgrp(int pgrp);
1.1       root       32: 
                     33: int sys_ftime()
                     34: {
                     35:        return -ENOSYS;
                     36: }
                     37: 
                     38: int sys_break()
                     39: {
                     40:        return -ENOSYS;
                     41: }
                     42: 
1.1.1.4 ! root       43: int sys_stty()
1.1       root       44: {
                     45:        return -ENOSYS;
                     46: }
                     47: 
1.1.1.4 ! root       48: int sys_gtty()
1.1       root       49: {
                     50:        return -ENOSYS;
                     51: }
                     52: 
1.1.1.4 ! root       53: int sys_prof()
1.1       root       54: {
                     55:        return -ENOSYS;
                     56: }
                     57: 
1.1.1.4 ! root       58: extern void hard_reset_now(void);
        !            59: 
        !            60: /*
        !            61:  * Reboot system call: for obvious reasons only root may call it,
        !            62:  * and even root needs to set up some magic numbers in the registers
        !            63:  * so that some mistake won't make this reboot the whole machine.
        !            64:  * You can also set the meaning of the ctrl-alt-del-key here.
        !            65:  *
        !            66:  * reboot doesn't sync: do that yourself before calling this.
        !            67:  */
        !            68: int sys_reboot(int magic, int magic_too, int flag)
1.1       root       69: {
1.1.1.4 ! root       70:        if (!suser())
        !            71:                return -EPERM;
        !            72:        if (magic != 0xfee1dead || magic_too != 672274793)
        !            73:                return -EINVAL;
        !            74:        if (flag == 0x01234567)
        !            75:                hard_reset_now();
        !            76:        else if (flag == 0x89ABCDEF)
        !            77:                C_A_D = 1;
        !            78:        else if (!flag)
        !            79:                C_A_D = 0;
        !            80:        else
        !            81:                return -EINVAL;
        !            82:        return (0);
1.1       root       83: }
                     84: 
1.1.1.4 ! root       85: /*
        !            86:  * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
        !            87:  * As it's called within an interrupt, it may NOT sync: the only choice
        !            88:  * is wether to reboot at once, or just ignore the ctrl-alt-del.
        !            89:  */
        !            90: void ctrl_alt_del(void)
1.1       root       91: {
1.1.1.4 ! root       92:        if (C_A_D)
        !            93:                hard_reset_now();
1.1       root       94: }
1.1.1.4 ! root       95:        
1.1       root       96: 
1.1.1.3   root       97: /*
                     98:  * This is done BSD-style, with no consideration of the saved gid, except
                     99:  * that if you set the effective gid, it sets the saved gid too.  This 
                    100:  * makes it possible for a setgid program to completely drop its privileges,
                    101:  * which is often a useful assertion to make when you are doing a security
                    102:  * audit over a program.
                    103:  *
                    104:  * The general idea is that a program which uses just setregid() will be
                    105:  * 100% compatible with BSD.  A program which uses just setgid() will be
                    106:  * 100% compatible with POSIX w/ Saved ID's. 
                    107:  */
1.1.1.2   root      108: int sys_setregid(int rgid, int egid)
1.1       root      109: {
1.1.1.2   root      110:        if (rgid>0) {
                    111:                if ((current->gid == rgid) || 
                    112:                    suser())
                    113:                        current->gid = rgid;
                    114:                else
                    115:                        return(-EPERM);
                    116:        }
                    117:        if (egid>0) {
                    118:                if ((current->gid == egid) ||
                    119:                    (current->egid == egid) ||
1.1.1.3   root      120:                    suser()) {
1.1.1.2   root      121:                        current->egid = egid;
1.1.1.3   root      122:                        current->sgid = egid;
                    123:                } else
1.1.1.2   root      124:                        return(-EPERM);
                    125:        }
1.1       root      126:        return 0;
                    127: }
                    128: 
1.1.1.3   root      129: /*
                    130:  * setgid() is implemeneted like SysV w/ SAVED_IDS 
                    131:  */
1.1.1.2   root      132: int sys_setgid(int gid)
                    133: {
1.1.1.3   root      134:        if (suser())
                    135:                current->gid = current->egid = current->sgid = gid;
                    136:        else if ((gid == current->gid) || (gid == current->sgid))
                    137:                current->egid = gid;
                    138:        else
                    139:                return -EPERM;
                    140:        return 0;
1.1.1.2   root      141: }
                    142: 
1.1       root      143: int sys_acct()
                    144: {
                    145:        return -ENOSYS;
                    146: }
                    147: 
                    148: int sys_phys()
                    149: {
                    150:        return -ENOSYS;
                    151: }
                    152: 
                    153: int sys_lock()
                    154: {
                    155:        return -ENOSYS;
                    156: }
                    157: 
                    158: int sys_mpx()
                    159: {
                    160:        return -ENOSYS;
                    161: }
                    162: 
                    163: int sys_ulimit()
                    164: {
                    165:        return -ENOSYS;
                    166: }
                    167: 
                    168: int sys_time(long * tloc)
                    169: {
                    170:        int i;
                    171: 
                    172:        i = CURRENT_TIME;
                    173:        if (tloc) {
                    174:                verify_area(tloc,4);
                    175:                put_fs_long(i,(unsigned long *)tloc);
                    176:        }
                    177:        return i;
                    178: }
                    179: 
1.1.1.2   root      180: /*
                    181:  * Unprivileged users may change the real user id to the effective uid
1.1.1.3   root      182:  * or vice versa.  (BSD-style)
                    183:  *
                    184:  * When you set the effective uid, it sets the saved uid too.  This 
                    185:  * makes it possible for a setuid program to completely drop its privileges,
                    186:  * which is often a useful assertion to make when you are doing a security
                    187:  * audit over a program.
                    188:  *
                    189:  * The general idea is that a program which uses just setreuid() will be
                    190:  * 100% compatible with BSD.  A program which uses just setuid() will be
                    191:  * 100% compatible with POSIX w/ Saved ID's. 
1.1.1.2   root      192:  */
                    193: int sys_setreuid(int ruid, int euid)
1.1       root      194: {
1.1.1.2   root      195:        int old_ruid = current->uid;
                    196:        
                    197:        if (ruid>0) {
                    198:                if ((current->euid==ruid) ||
                    199:                     (old_ruid == ruid) ||
                    200:                    suser())
                    201:                        current->uid = ruid;
1.1       root      202:                else
1.1.1.2   root      203:                        return(-EPERM);
                    204:        }
                    205:        if (euid>0) {
                    206:                if ((old_ruid == euid) ||
                    207:                     (current->euid == euid) ||
1.1.1.3   root      208:                    suser()) {
1.1.1.2   root      209:                        current->euid = euid;
1.1.1.3   root      210:                        current->suid = euid;
                    211:                } else {
1.1.1.2   root      212:                        current->uid = old_ruid;
                    213:                        return(-EPERM);
                    214:                }
                    215:        }
1.1       root      216:        return 0;
                    217: }
                    218: 
1.1.1.3   root      219: /*
                    220:  * setuid() is implemeneted like SysV w/ SAVED_IDS 
                    221:  * 
                    222:  * Note that SAVED_ID's is deficient in that a setuid root program
                    223:  * like sendmail, for example, cannot set its uid to be a normal 
                    224:  * user and then switch back, because if you're root, setuid() sets
                    225:  * the saved uid too.  If you don't like this, blame the bright people
                    226:  * in the POSIX commmittee and/or USG.  Note that the BSD-style setreuid()
                    227:  * will allow a root program to temporarily drop privileges and be able to
                    228:  * regain them by swapping the real and effective uid.  
                    229:  */
1.1.1.2   root      230: int sys_setuid(int uid)
                    231: {
1.1.1.3   root      232:        if (suser())
                    233:                current->uid = current->euid = current->suid = uid;
                    234:        else if ((uid == current->uid) || (uid == current->suid))
                    235:                current->euid = uid;
                    236:        else
                    237:                return -EPERM;
                    238:        return(0);
1.1.1.2   root      239: }
                    240: 
1.1       root      241: int sys_stime(long * tptr)
                    242: {
1.1.1.2   root      243:        if (!suser())
                    244:                return -EPERM;
1.1       root      245:        startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
1.1.1.3   root      246:        jiffies_offset = 0;
1.1       root      247:        return 0;
                    248: }
                    249: 
                    250: int sys_times(struct tms * tbuf)
                    251: {
1.1.1.2   root      252:        if (tbuf) {
                    253:                verify_area(tbuf,sizeof *tbuf);
                    254:                put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
                    255:                put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
                    256:                put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
                    257:                put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
                    258:        }
1.1       root      259:        return jiffies;
                    260: }
                    261: 
                    262: int sys_brk(unsigned long end_data_seg)
                    263: {
                    264:        if (end_data_seg >= current->end_code &&
                    265:            end_data_seg < current->start_stack - 16384)
                    266:                current->brk = end_data_seg;
                    267:        return current->brk;
                    268: }
                    269: 
                    270: /*
                    271:  * This needs some heave checking ...
                    272:  * I just haven't get the stomach for it. I also don't fully
                    273:  * understand sessions/pgrp etc. Let somebody who does explain it.
1.1.1.3   root      274:  *
                    275:  * OK, I think I have the protection semantics right.... this is really
                    276:  * only important on a multi-user system anyway, to make sure one user
                    277:  * can't send a signal to a process owned by another.  -TYT, 12/12/91
1.1       root      278:  */
                    279: int sys_setpgid(int pid, int pgid)
                    280: {
1.1.1.3   root      281:        int i; 
1.1       root      282: 
                    283:        if (!pid)
                    284:                pid = current->pid;
                    285:        if (!pgid)
1.1.1.2   root      286:                pgid = current->pid;
1.1.1.3   root      287:        if (pgid < 0)
                    288:                return -EINVAL;
1.1       root      289:        for (i=0 ; i<NR_TASKS ; i++)
1.1.1.3   root      290:                if (task[i] && (task[i]->pid == pid) &&
                    291:                    ((task[i]->p_pptr == current) || 
                    292:                     (task[i] == current))) {
1.1       root      293:                        if (task[i]->leader)
                    294:                                return -EPERM;
1.1.1.3   root      295:                        if ((task[i]->session != current->session) ||
                    296:                            ((pgid != pid) && 
                    297:                             (session_of_pgrp(pgid) != current->session)))
1.1       root      298:                                return -EPERM;
                    299:                        task[i]->pgrp = pgid;
                    300:                        return 0;
                    301:                }
                    302:        return -ESRCH;
                    303: }
                    304: 
                    305: int sys_getpgrp(void)
                    306: {
                    307:        return current->pgrp;
                    308: }
                    309: 
                    310: int sys_setsid(void)
                    311: {
1.1.1.2   root      312:        if (current->leader && !suser())
1.1       root      313:                return -EPERM;
                    314:        current->leader = 1;
                    315:        current->session = current->pgrp = current->pid;
                    316:        current->tty = -1;
                    317:        return current->pgrp;
                    318: }
                    319: 
1.1.1.3   root      320: /*
                    321:  * Supplementary group ID's
                    322:  */
                    323: int sys_getgroups(int gidsetsize, gid_t *grouplist)
                    324: {
                    325:        int     i;
                    326: 
                    327:        if (gidsetsize)
                    328:                verify_area(grouplist, sizeof(gid_t) * gidsetsize);
                    329: 
                    330:        for (i = 0; (i < NGROUPS) && (current->groups[i] != NOGROUP);
                    331:             i++, grouplist++) {
                    332:                if (gidsetsize) {
                    333:                        if (i >= gidsetsize)
                    334:                                return -EINVAL;
                    335:                        put_fs_word(current->groups[i], (short *) grouplist);
                    336:                }
                    337:        }
                    338:        return(i);
                    339: }
                    340: 
                    341: int sys_setgroups(int gidsetsize, gid_t *grouplist)
                    342: {
                    343:        int     i;
                    344: 
                    345:        if (!suser())
                    346:                return -EPERM;
                    347:        if (gidsetsize > NGROUPS)
                    348:                return -EINVAL;
                    349:        for (i = 0; i < gidsetsize; i++, grouplist++) {
                    350:                current->groups[i] = get_fs_word((unsigned short *) grouplist);
                    351:        }
                    352:        if (i < NGROUPS)
                    353:                current->groups[i] = NOGROUP;
                    354:        return 0;
                    355: }
                    356: 
                    357: int in_group_p(gid_t grp)
                    358: {
                    359:        int     i;
                    360: 
                    361:        if (grp == current->egid)
                    362:                return 1;
                    363: 
                    364:        for (i = 0; i < NGROUPS; i++) {
                    365:                if (current->groups[i] == NOGROUP)
                    366:                        break;
                    367:                if (current->groups[i] == grp)
                    368:                        return 1;
                    369:        }
                    370:        return 0;
                    371: }
                    372: 
                    373: static struct utsname thisname = {
                    374:        UTS_SYSNAME, UTS_NODENAME, UTS_RELEASE, UTS_VERSION, UTS_MACHINE
                    375: };
                    376: 
1.1       root      377: int sys_uname(struct utsname * name)
                    378: {
                    379:        int i;
                    380: 
1.1.1.2   root      381:        if (!name) return -ERROR;
1.1       root      382:        verify_area(name,sizeof *name);
                    383:        for(i=0;i<sizeof *name;i++)
                    384:                put_fs_byte(((char *) &thisname)[i],i+(char *) name);
1.1.1.2   root      385:        return 0;
1.1       root      386: }
                    387: 
1.1.1.3   root      388: /*
                    389:  * Only sethostname; gethostname can be implemented by calling uname()
                    390:  */
                    391: int sys_sethostname(char *name, int len)
                    392: {
                    393:        int     i;
                    394:        
                    395:        if (!suser())
                    396:                return -EPERM;
                    397:        if (len > MAXHOSTNAMELEN)
                    398:                return -EINVAL;
                    399:        for (i=0; i < len; i++) {
                    400:                if ((thisname.nodename[i] = get_fs_byte(name+i)) == 0)
                    401:                        break;
                    402:        }
                    403:        if (thisname.nodename[i]) {
                    404:                thisname.nodename[i>MAXHOSTNAMELEN ? MAXHOSTNAMELEN : i] = 0;
                    405:        }
                    406:        return 0;
                    407: }
                    408: 
                    409: int sys_getrlimit(int resource, struct rlimit *rlim)
                    410: {
                    411:        if (resource >= RLIM_NLIMITS)
                    412:                return -EINVAL;
                    413:        verify_area(rlim,sizeof *rlim);
                    414:        put_fs_long(current->rlim[resource].rlim_cur, 
                    415:                    (unsigned long *) rlim);
                    416:        put_fs_long(current->rlim[resource].rlim_max, 
                    417:                    ((unsigned long *) rlim)+1);
                    418:        return 0;       
                    419: }
                    420: 
                    421: int sys_setrlimit(int resource, struct rlimit *rlim)
                    422: {
                    423:        struct rlimit new, *old;
                    424: 
                    425:        if (resource >= RLIM_NLIMITS)
                    426:                return -EINVAL;
                    427:        old = current->rlim + resource;
                    428:        new.rlim_cur = get_fs_long((unsigned long *) rlim);
                    429:        new.rlim_max = get_fs_long(((unsigned long *) rlim)+1);
                    430:        if (((new.rlim_cur > old->rlim_max) ||
                    431:             (new.rlim_max > old->rlim_max)) &&
                    432:            !suser())
                    433:                return -EPERM;
                    434:        *old = new;
                    435:        return 0;
                    436: }
                    437: 
                    438: /*
                    439:  * It would make sense to put struct rusuage in the task_struct,
                    440:  * except that would make the task_struct be *really big*.  After
                    441:  * task_struct gets moved into malloc'ed memory, it would
                    442:  * make sense to do this.  It will make moving the rest of the information
                    443:  * a lot simpler!  (Which we're not doing right now because we're not
                    444:  * measuring them yet).
                    445:  */
                    446: int sys_getrusage(int who, struct rusage *ru)
                    447: {
                    448:        struct rusage r;
                    449:        unsigned long   *lp, *lpend, *dest;
                    450: 
                    451:        if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
                    452:                return -EINVAL;
                    453:        verify_area(ru, sizeof *ru);
                    454:        memset((char *) &r, 0, sizeof(r));
                    455:        if (who == RUSAGE_SELF) {
                    456:                r.ru_utime.tv_sec = CT_TO_SECS(current->utime);
                    457:                r.ru_utime.tv_usec = CT_TO_USECS(current->utime);
                    458:                r.ru_stime.tv_sec = CT_TO_SECS(current->stime);
                    459:                r.ru_stime.tv_usec = CT_TO_USECS(current->stime);
                    460:        } else {
                    461:                r.ru_utime.tv_sec = CT_TO_SECS(current->cutime);
                    462:                r.ru_utime.tv_usec = CT_TO_USECS(current->cutime);
                    463:                r.ru_stime.tv_sec = CT_TO_SECS(current->cstime);
                    464:                r.ru_stime.tv_usec = CT_TO_USECS(current->cstime);
                    465:        }
                    466:        lp = (unsigned long *) &r;
                    467:        lpend = (unsigned long *) (&r+1);
                    468:        dest = (unsigned long *) ru;
                    469:        for (; lp < lpend; lp++, dest++) 
                    470:                put_fs_long(*lp, dest);
                    471:        return(0);
                    472: }
                    473: 
                    474: int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
                    475: {
                    476:        if (tv) {
                    477:                verify_area(tv, sizeof *tv);
                    478:                put_fs_long(startup_time + CT_TO_SECS(jiffies+jiffies_offset),
                    479:                            (unsigned long *) tv);
                    480:                put_fs_long(CT_TO_USECS(jiffies+jiffies_offset), 
                    481:                            ((unsigned long *) tv)+1);
                    482:        }
                    483:        if (tz) {
                    484:                verify_area(tz, sizeof *tz);
                    485:                put_fs_long(sys_tz.tz_minuteswest, (unsigned long *) tz);
                    486:                put_fs_long(sys_tz.tz_dsttime, ((unsigned long *) tz)+1);
                    487:        }
                    488:        return 0;
                    489: }
                    490: 
                    491: /*
                    492:  * The first time we set the timezone, we will warp the clock so that
                    493:  * it is ticking GMT time instead of local time.  Presumably, 
                    494:  * if someone is setting the timezone then we are running in an
                    495:  * environment where the programs understand about timezones.
                    496:  * This should be done at boot time in the /etc/rc script, as
                    497:  * soon as possible, so that the clock can be set right.  Otherwise,
                    498:  * various programs will get confused when the clock gets warped.
                    499:  */
                    500: int sys_settimeofday(struct timeval *tv, struct timezone *tz)
                    501: {
                    502:        static int      firsttime = 1;
                    503:        void            adjust_clock();
                    504: 
                    505:        if (!suser())
                    506:                return -EPERM;
                    507:        if (tz) {
                    508:                sys_tz.tz_minuteswest = get_fs_long((unsigned long *) tz);
                    509:                sys_tz.tz_dsttime = get_fs_long(((unsigned long *) tz)+1);
                    510:                if (firsttime) {
                    511:                        firsttime = 0;
                    512:                        if (!tv)
                    513:                                adjust_clock();
                    514:                }
                    515:        }
                    516:        if (tv) {
                    517:                int sec, usec;
                    518: 
                    519:                sec = get_fs_long((unsigned long *)tv);
                    520:                usec = get_fs_long(((unsigned long *)tv)+1);
                    521:        
                    522:                startup_time = sec - jiffies/HZ;
                    523:                jiffies_offset = usec * HZ / 1000000 - jiffies%HZ;
                    524:        }
                    525:        return 0;
                    526: }
                    527: 
                    528: /*
                    529:  * Adjust the time obtained from the CMOS to be GMT time instead of
                    530:  * local time.
                    531:  * 
                    532:  * This is ugly, but preferable to the alternatives.  Otherwise we
                    533:  * would either need to write a program to do it in /etc/rc (and risk
                    534:  * confusion if the program gets run more than once; it would also be 
                    535:  * hard to make the program warp the clock precisely n hours)  or
                    536:  * compile in the timezone information into the kernel.  Bad, bad....
                    537:  *
                    538:  * XXX Currently does not adjust for daylight savings time.  May not
                    539:  * need to do anything, depending on how smart (dumb?) the BIOS
                    540:  * is.  Blast it all.... the best thing to do not depend on the CMOS
                    541:  * clock at all, but get the time via NTP or timed if you're on a 
                    542:  * network....                         - TYT, 1/1/92
                    543:  */
                    544: void adjust_clock()
                    545: {
                    546:        startup_time += sys_tz.tz_minuteswest*60;
                    547: }
                    548: 
1.1       root      549: int sys_umask(int mask)
                    550: {
                    551:        int old = current->umask;
                    552: 
                    553:        current->umask = mask & 0777;
                    554:        return (old);
                    555: }
1.1.1.3   root      556: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.