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