|
|
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);
1.1.1.5 ! root 460: r.ru_minflt = current->min_flt;
! 461: r.ru_majflt = current->maj_flt;
1.1.1.3 root 462: } else {
463: r.ru_utime.tv_sec = CT_TO_SECS(current->cutime);
464: r.ru_utime.tv_usec = CT_TO_USECS(current->cutime);
465: r.ru_stime.tv_sec = CT_TO_SECS(current->cstime);
466: r.ru_stime.tv_usec = CT_TO_USECS(current->cstime);
1.1.1.5 ! root 467: r.ru_minflt = current->cmin_flt;
! 468: r.ru_majflt = current->cmaj_flt;
1.1.1.3 root 469: }
470: lp = (unsigned long *) &r;
471: lpend = (unsigned long *) (&r+1);
472: dest = (unsigned long *) ru;
473: for (; lp < lpend; lp++, dest++)
474: put_fs_long(*lp, dest);
475: return(0);
476: }
477:
478: int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
479: {
480: if (tv) {
481: verify_area(tv, sizeof *tv);
482: put_fs_long(startup_time + CT_TO_SECS(jiffies+jiffies_offset),
483: (unsigned long *) tv);
484: put_fs_long(CT_TO_USECS(jiffies+jiffies_offset),
485: ((unsigned long *) tv)+1);
486: }
487: if (tz) {
488: verify_area(tz, sizeof *tz);
489: put_fs_long(sys_tz.tz_minuteswest, (unsigned long *) tz);
490: put_fs_long(sys_tz.tz_dsttime, ((unsigned long *) tz)+1);
491: }
492: return 0;
493: }
494:
495: /*
496: * The first time we set the timezone, we will warp the clock so that
497: * it is ticking GMT time instead of local time. Presumably,
498: * if someone is setting the timezone then we are running in an
499: * environment where the programs understand about timezones.
500: * This should be done at boot time in the /etc/rc script, as
501: * soon as possible, so that the clock can be set right. Otherwise,
502: * various programs will get confused when the clock gets warped.
503: */
504: int sys_settimeofday(struct timeval *tv, struct timezone *tz)
505: {
506: static int firsttime = 1;
507: void adjust_clock();
508:
509: if (!suser())
510: return -EPERM;
511: if (tz) {
512: sys_tz.tz_minuteswest = get_fs_long((unsigned long *) tz);
513: sys_tz.tz_dsttime = get_fs_long(((unsigned long *) tz)+1);
514: if (firsttime) {
515: firsttime = 0;
516: if (!tv)
517: adjust_clock();
518: }
519: }
520: if (tv) {
521: int sec, usec;
522:
523: sec = get_fs_long((unsigned long *)tv);
524: usec = get_fs_long(((unsigned long *)tv)+1);
525:
526: startup_time = sec - jiffies/HZ;
527: jiffies_offset = usec * HZ / 1000000 - jiffies%HZ;
528: }
529: return 0;
530: }
531:
532: /*
533: * Adjust the time obtained from the CMOS to be GMT time instead of
534: * local time.
535: *
536: * This is ugly, but preferable to the alternatives. Otherwise we
537: * would either need to write a program to do it in /etc/rc (and risk
538: * confusion if the program gets run more than once; it would also be
539: * hard to make the program warp the clock precisely n hours) or
540: * compile in the timezone information into the kernel. Bad, bad....
541: *
542: * XXX Currently does not adjust for daylight savings time. May not
543: * need to do anything, depending on how smart (dumb?) the BIOS
544: * is. Blast it all.... the best thing to do not depend on the CMOS
545: * clock at all, but get the time via NTP or timed if you're on a
546: * network.... - TYT, 1/1/92
547: */
548: void adjust_clock()
549: {
550: startup_time += sys_tz.tz_minuteswest*60;
551: }
552:
1.1 root 553: int sys_umask(int mask)
554: {
555: int old = current->umask;
556:
557: current->umask = mask & 0777;
558: return (old);
559: }
1.1.1.3 root 560:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.