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

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

unix.superglobalmegacorp.com

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