* added 0.99 linux version
[mascara-docs.git] / i386 / linux / linux-2.3.21 / kernel / sys.c
blobbc4012cac22e5a06cac1c5a60d3ee685efcfac0d
1 /*
2 * linux/kernel/sys.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 #include <linux/mm.h>
8 #include <linux/utsname.h>
9 #include <linux/mman.h>
10 #include <linux/smp_lock.h>
11 #include <linux/notifier.h>
12 #include <linux/reboot.h>
13 #include <linux/prctl.h>
14 #include <linux/init.h>
16 #include <asm/uaccess.h>
17 #include <asm/io.h>
20 * this indicates whether you can reboot with ctrl-alt-del: the default is yes
23 int C_A_D = 1;
27 * Notifier list for kernel code which wants to be called
28 * at shutdown. This is used to stop any idling DMA operations
29 * and the like.
32 struct notifier_block *reboot_notifier_list = NULL;
34 int register_reboot_notifier(struct notifier_block * nb)
36 return notifier_chain_register(&reboot_notifier_list, nb);
39 int unregister_reboot_notifier(struct notifier_block * nb)
41 return notifier_chain_unregister(&reboot_notifier_list, nb);
44 asmlinkage long sys_ni_syscall(void)
46 return -ENOSYS;
49 static int proc_sel(struct task_struct *p, int which, int who)
51 if(p->pid)
53 switch (which) {
54 case PRIO_PROCESS:
55 if (!who && p == current)
56 return 1;
57 return(p->pid == who);
58 case PRIO_PGRP:
59 if (!who)
60 who = current->pgrp;
61 return(p->pgrp == who);
62 case PRIO_USER:
63 if (!who)
64 who = current->uid;
65 return(p->uid == who);
68 return 0;
71 asmlinkage long sys_setpriority(int which, int who, int niceval)
73 struct task_struct *p;
74 unsigned int priority;
75 int error;
77 if (which > 2 || which < 0)
78 return -EINVAL;
80 /* normalize: avoid signed division (rounding problems) */
81 error = ESRCH;
82 priority = niceval;
83 if (niceval < 0)
84 priority = -niceval;
85 if (priority > 20)
86 priority = 20;
87 priority = (priority * DEF_PRIORITY + 10) / 20 + DEF_PRIORITY;
89 if (niceval >= 0) {
90 priority = 2*DEF_PRIORITY - priority;
91 if (!priority)
92 priority = 1;
95 read_lock(&tasklist_lock);
96 for_each_task(p) {
97 if (!proc_sel(p, which, who))
98 continue;
99 if (p->uid != current->euid &&
100 p->uid != current->uid && !capable(CAP_SYS_NICE)) {
101 error = EPERM;
102 continue;
104 if (error == ESRCH)
105 error = 0;
106 if (priority > p->priority && !capable(CAP_SYS_NICE))
107 error = EACCES;
108 else
109 p->priority = priority;
111 read_unlock(&tasklist_lock);
113 return -error;
117 * Ugh. To avoid negative return values, "getpriority()" will
118 * not return the normal nice-value, but a value that has been
119 * offset by 20 (ie it returns 0..40 instead of -20..20)
121 asmlinkage long sys_getpriority(int which, int who)
123 struct task_struct *p;
124 long max_prio = -ESRCH;
126 if (which > 2 || which < 0)
127 return -EINVAL;
129 read_lock(&tasklist_lock);
130 for_each_task (p) {
131 if (!proc_sel(p, which, who))
132 continue;
133 if (p->priority > max_prio)
134 max_prio = p->priority;
136 read_unlock(&tasklist_lock);
138 /* scale the priority from timeslice to 0..40 */
139 if (max_prio > 0)
140 max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY;
141 return max_prio;
146 * Reboot system call: for obvious reasons only root may call it,
147 * and even root needs to set up some magic numbers in the registers
148 * so that some mistake won't make this reboot the whole machine.
149 * You can also set the meaning of the ctrl-alt-del-key here.
151 * reboot doesn't sync: do that yourself before calling this.
153 asmlinkage long sys_reboot(int magic1, int magic2, int cmd, void * arg)
155 char buffer[256];
157 /* We only trust the superuser with rebooting the system. */
158 if (!capable(CAP_SYS_BOOT))
159 return -EPERM;
161 /* For safety, we require "magic" arguments. */
162 if (magic1 != LINUX_REBOOT_MAGIC1 ||
163 (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
164 magic2 != LINUX_REBOOT_MAGIC2B))
165 return -EINVAL;
167 lock_kernel();
168 switch (cmd) {
169 case LINUX_REBOOT_CMD_RESTART:
170 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
171 printk(KERN_EMERG "Restarting system.\n");
172 machine_restart(NULL);
173 break;
175 case LINUX_REBOOT_CMD_CAD_ON:
176 C_A_D = 1;
177 break;
179 case LINUX_REBOOT_CMD_CAD_OFF:
180 C_A_D = 0;
181 break;
183 case LINUX_REBOOT_CMD_HALT:
184 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
185 printk(KERN_EMERG "System halted.\n");
186 machine_halt();
187 do_exit(0);
188 break;
190 case LINUX_REBOOT_CMD_POWER_OFF:
191 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
192 printk(KERN_EMERG "Power down.\n");
193 machine_power_off();
194 do_exit(0);
195 break;
197 case LINUX_REBOOT_CMD_RESTART2:
198 if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) {
199 unlock_kernel();
200 return -EFAULT;
202 buffer[sizeof(buffer) - 1] = '\0';
204 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
205 printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
206 machine_restart(buffer);
207 break;
209 default:
210 unlock_kernel();
211 return -EINVAL;
212 break;
214 unlock_kernel();
215 return 0;
219 * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
220 * As it's called within an interrupt, it may NOT sync: the only choice
221 * is whether to reboot at once, or just ignore the ctrl-alt-del.
223 void ctrl_alt_del(void)
225 if (C_A_D) {
226 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
227 machine_restart(NULL);
228 } else
229 kill_proc(1, SIGINT, 1);
234 * Unprivileged users may change the real gid to the effective gid
235 * or vice versa. (BSD-style)
237 * If you set the real gid at all, or set the effective gid to a value not
238 * equal to the real gid, then the saved gid is set to the new effective gid.
240 * This makes it possible for a setgid program to completely drop its
241 * privileges, which is often a useful assertion to make when you are doing
242 * a security audit over a program.
244 * The general idea is that a program which uses just setregid() will be
245 * 100% compatible with BSD. A program which uses just setgid() will be
246 * 100% compatible with POSIX with saved IDs.
248 * SMP: There are not races, the GIDs are checked only by filesystem
249 * operations (as far as semantic preservation is concerned).
251 asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
253 int old_rgid = current->gid;
254 int old_egid = current->egid;
256 if (rgid != (gid_t) -1) {
257 if ((old_rgid == rgid) ||
258 (current->egid==rgid) ||
259 capable(CAP_SETGID))
260 current->gid = rgid;
261 else
262 return -EPERM;
264 if (egid != (gid_t) -1) {
265 if ((old_rgid == egid) ||
266 (current->egid == egid) ||
267 (current->sgid == egid) ||
268 capable(CAP_SETGID))
269 current->fsgid = current->egid = egid;
270 else {
271 current->gid = old_rgid;
272 return -EPERM;
275 if (rgid != (gid_t) -1 ||
276 (egid != (gid_t) -1 && egid != old_rgid))
277 current->sgid = current->egid;
278 current->fsgid = current->egid;
279 if (current->egid != old_egid)
280 current->dumpable = 0;
281 return 0;
285 * setgid() is implemented like SysV w/ SAVED_IDS
287 * SMP: Same implicit races as above.
289 asmlinkage long sys_setgid(gid_t gid)
291 int old_egid = current->egid;
293 if (capable(CAP_SETGID))
294 current->gid = current->egid = current->sgid = current->fsgid = gid;
295 else if ((gid == current->gid) || (gid == current->sgid))
296 current->egid = current->fsgid = gid;
297 else
298 return -EPERM;
300 if (current->egid != old_egid)
301 current->dumpable = 0;
302 return 0;
306 * cap_emulate_setxuid() fixes the effective / permitted capabilities of
307 * a process after a call to setuid, setreuid, or setresuid.
309 * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
310 * {r,e,s}uid != 0, the permitted and effective capabilities are
311 * cleared.
313 * 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
314 * capabilities of the process are cleared.
316 * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
317 * capabilities are set to the permitted capabilities.
319 * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
320 * never happen.
322 * -astor
324 extern inline void cap_emulate_setxuid(int old_ruid, int old_euid,
325 int old_suid)
327 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
328 (current->uid != 0 && current->euid != 0 && current->suid != 0)) {
329 cap_clear(current->cap_permitted);
330 cap_clear(current->cap_effective);
332 if (old_euid == 0 && current->euid != 0) {
333 cap_clear(current->cap_effective);
335 if (old_euid != 0 && current->euid == 0) {
336 current->cap_effective = current->cap_permitted;
341 * Unprivileged users may change the real uid to the effective uid
342 * or vice versa. (BSD-style)
344 * If you set the real uid at all, or set the effective uid to a value not
345 * equal to the real uid, then the saved uid is set to the new effective uid.
347 * This makes it possible for a setuid program to completely drop its
348 * privileges, which is often a useful assertion to make when you are doing
349 * a security audit over a program.
351 * The general idea is that a program which uses just setreuid() will be
352 * 100% compatible with BSD. A program which uses just setuid() will be
353 * 100% compatible with POSIX with saved IDs.
355 asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
357 int old_ruid, old_euid, old_suid, new_ruid;
359 new_ruid = old_ruid = current->uid;
360 old_euid = current->euid;
361 old_suid = current->suid;
362 if (ruid != (uid_t) -1) {
363 if ((old_ruid == ruid) ||
364 (current->euid==ruid) ||
365 capable(CAP_SETUID))
366 new_ruid = ruid;
367 else
368 return -EPERM;
370 if (euid != (uid_t) -1) {
371 if ((old_ruid == euid) ||
372 (current->euid == euid) ||
373 (current->suid == euid) ||
374 capable(CAP_SETUID))
375 current->fsuid = current->euid = euid;
376 else
377 return -EPERM;
379 if (ruid != (uid_t) -1 ||
380 (euid != (uid_t) -1 && euid != old_ruid))
381 current->suid = current->euid;
382 current->fsuid = current->euid;
383 if (current->euid != old_euid)
384 current->dumpable = 0;
386 if(new_ruid != old_ruid) {
387 /* What if a process setreuid()'s and this brings the
388 * new uid over his NPROC rlimit? We can check this now
389 * cheaply with the new uid cache, so if it matters
390 * we should be checking for it. -DaveM
392 free_uid(current);
393 current->uid = new_ruid;
394 alloc_uid(current);
397 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
398 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
401 return 0;
407 * setuid() is implemented like SysV with SAVED_IDS
409 * Note that SAVED_ID's is deficient in that a setuid root program
410 * like sendmail, for example, cannot set its uid to be a normal
411 * user and then switch back, because if you're root, setuid() sets
412 * the saved uid too. If you don't like this, blame the bright people
413 * in the POSIX committee and/or USG. Note that the BSD-style setreuid()
414 * will allow a root program to temporarily drop privileges and be able to
415 * regain them by swapping the real and effective uid.
417 asmlinkage long sys_setuid(uid_t uid)
419 int old_euid = current->euid;
420 int old_ruid, old_suid, new_ruid;
422 old_ruid = new_ruid = current->uid;
423 old_suid = current->suid;
424 if (capable(CAP_SETUID))
425 new_ruid = current->euid = current->suid = current->fsuid = uid;
426 else if ((uid == current->uid) || (uid == current->suid))
427 current->fsuid = current->euid = uid;
428 else
429 return -EPERM;
431 if (current->euid != old_euid)
432 current->dumpable = 0;
434 if (new_ruid != old_ruid) {
435 /* See comment above about NPROC rlimit issues... */
436 free_uid(current);
437 current->uid = new_ruid;
438 alloc_uid(current);
441 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
442 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
445 return 0;
450 * This function implements a generic ability to update ruid, euid,
451 * and suid. This allows you to implement the 4.4 compatible seteuid().
453 asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
455 int old_ruid = current->uid;
456 int old_euid = current->euid;
457 int old_suid = current->suid;
459 if (!capable(CAP_SETUID)) {
460 if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
461 (ruid != current->euid) && (ruid != current->suid))
462 return -EPERM;
463 if ((euid != (uid_t) -1) && (euid != current->uid) &&
464 (euid != current->euid) && (euid != current->suid))
465 return -EPERM;
466 if ((suid != (uid_t) -1) && (suid != current->uid) &&
467 (suid != current->euid) && (suid != current->suid))
468 return -EPERM;
470 if (ruid != (uid_t) -1) {
471 /* See above commentary about NPROC rlimit issues here. */
472 free_uid(current);
473 current->uid = ruid;
474 alloc_uid(current);
476 if (euid != (uid_t) -1) {
477 if (euid != current->euid)
478 current->dumpable = 0;
479 current->euid = euid;
480 current->fsuid = euid;
482 if (suid != (uid_t) -1)
483 current->suid = suid;
485 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
486 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
489 return 0;
492 asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
494 int retval;
496 if (!(retval = put_user(current->uid, ruid)) &&
497 !(retval = put_user(current->euid, euid)))
498 retval = put_user(current->suid, suid);
500 return retval;
504 * Same as above, but for rgid, egid, sgid.
506 asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
508 if (!capable(CAP_SETGID)) {
509 if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
510 (rgid != current->egid) && (rgid != current->sgid))
511 return -EPERM;
512 if ((egid != (gid_t) -1) && (egid != current->gid) &&
513 (egid != current->egid) && (egid != current->sgid))
514 return -EPERM;
515 if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
516 (sgid != current->egid) && (sgid != current->sgid))
517 return -EPERM;
519 if (rgid != (gid_t) -1)
520 current->gid = rgid;
521 if (egid != (gid_t) -1) {
522 if (egid != current->egid)
523 current->dumpable = 0;
524 current->egid = egid;
525 current->fsgid = egid;
527 if (sgid != (gid_t) -1)
528 current->sgid = sgid;
529 return 0;
532 asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
534 int retval;
536 if (!(retval = put_user(current->gid, rgid)) &&
537 !(retval = put_user(current->egid, egid)))
538 retval = put_user(current->sgid, sgid);
540 return retval;
545 * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
546 * is used for "access()" and for the NFS daemon (letting nfsd stay at
547 * whatever uid it wants to). It normally shadows "euid", except when
548 * explicitly set by setfsuid() or for access..
550 asmlinkage long sys_setfsuid(uid_t uid)
552 int old_fsuid;
554 old_fsuid = current->fsuid;
555 if (uid == current->uid || uid == current->euid ||
556 uid == current->suid || uid == current->fsuid ||
557 capable(CAP_SETUID))
558 current->fsuid = uid;
559 if (current->fsuid != old_fsuid)
560 current->dumpable = 0;
562 /* We emulate fsuid by essentially doing a scaled-down version
563 * of what we did in setresuid and friends. However, we only
564 * operate on the fs-specific bits of the process' effective
565 * capabilities
567 * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
568 * if not, we might be a bit too harsh here.
571 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
572 if (old_fsuid == 0 && current->fsuid != 0) {
573 cap_t(current->cap_effective) &= ~CAP_FS_MASK;
575 if (old_fsuid != 0 && current->fsuid == 0) {
576 cap_t(current->cap_effective) |=
577 (cap_t(current->cap_permitted) & CAP_FS_MASK);
581 return old_fsuid;
585 * Samma på svenska..
587 asmlinkage long sys_setfsgid(gid_t gid)
589 int old_fsgid;
591 old_fsgid = current->fsgid;
592 if (gid == current->gid || gid == current->egid ||
593 gid == current->sgid || gid == current->fsgid ||
594 capable(CAP_SETGID))
595 current->fsgid = gid;
596 if (current->fsgid != old_fsgid)
597 current->dumpable = 0;
599 return old_fsgid;
602 asmlinkage long sys_times(struct tms * tbuf)
605 * In the SMP world we might just be unlucky and have one of
606 * the times increment as we use it. Since the value is an
607 * atomically safe type this is just fine. Conceptually its
608 * as if the syscall took an instant longer to occur.
610 if (tbuf)
611 if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
612 return -EFAULT;
613 return jiffies;
617 * This needs some heavy checking ...
618 * I just haven't the stomach for it. I also don't fully
619 * understand sessions/pgrp etc. Let somebody who does explain it.
621 * OK, I think I have the protection semantics right.... this is really
622 * only important on a multi-user system anyway, to make sure one user
623 * can't send a signal to a process owned by another. -TYT, 12/12/91
625 * Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
626 * LBT 04.03.94
629 asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
631 struct task_struct * p;
632 int err = -EINVAL;
634 if (!pid)
635 pid = current->pid;
636 if (!pgid)
637 pgid = pid;
638 if (pgid < 0)
639 return -EINVAL;
641 /* From this point forward we keep holding onto the tasklist lock
642 * so that our parent does not change from under us. -DaveM
644 read_lock(&tasklist_lock);
646 err = -ESRCH;
647 p = find_task_by_pid(pid);
648 if (!p)
649 goto out;
651 if (p->p_pptr == current || p->p_opptr == current) {
652 err = -EPERM;
653 if (p->session != current->session)
654 goto out;
655 err = -EACCES;
656 if (p->did_exec)
657 goto out;
658 } else if (p != current)
659 goto out;
660 err = -EPERM;
661 if (p->leader)
662 goto out;
663 if (pgid != pid) {
664 struct task_struct * tmp;
665 for_each_task (tmp) {
666 if (tmp->pgrp == pgid &&
667 tmp->session == current->session)
668 goto ok_pgid;
670 goto out;
673 ok_pgid:
674 p->pgrp = pgid;
675 err = 0;
676 out:
677 /* All paths lead to here, thus we are safe. -DaveM */
678 read_unlock(&tasklist_lock);
679 return err;
682 asmlinkage long sys_getpgid(pid_t pid)
684 if (!pid) {
685 return current->pgrp;
686 } else {
687 int retval;
688 struct task_struct *p;
690 read_lock(&tasklist_lock);
691 p = find_task_by_pid(pid);
693 retval = -ESRCH;
694 if (p)
695 retval = p->pgrp;
696 read_unlock(&tasklist_lock);
697 return retval;
701 asmlinkage long sys_getpgrp(void)
703 /* SMP - assuming writes are word atomic this is fine */
704 return current->pgrp;
707 asmlinkage long sys_getsid(pid_t pid)
709 if (!pid) {
710 return current->session;
711 } else {
712 int retval;
713 struct task_struct *p;
715 read_lock(&tasklist_lock);
716 p = find_task_by_pid(pid);
718 retval = -ESRCH;
719 if(p)
720 retval = p->session;
721 read_unlock(&tasklist_lock);
722 return retval;
726 asmlinkage long sys_setsid(void)
728 struct task_struct * p;
729 int err = -EPERM;
731 read_lock(&tasklist_lock);
732 for_each_task(p) {
733 if (p->pgrp == current->pid)
734 goto out;
737 current->leader = 1;
738 current->session = current->pgrp = current->pid;
739 current->tty = NULL;
740 current->tty_old_pgrp = 0;
741 err = current->pgrp;
742 out:
743 read_unlock(&tasklist_lock);
744 return err;
748 * Supplementary group IDs
750 asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist)
752 int i;
755 * SMP: Nobody else can change our grouplist. Thus we are
756 * safe.
759 if (gidsetsize < 0)
760 return -EINVAL;
761 i = current->ngroups;
762 if (gidsetsize) {
763 if (i > gidsetsize)
764 return -EINVAL;
765 if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i))
766 return -EFAULT;
768 return i;
772 * SMP: Our groups are not shared. We can copy to/from them safely
773 * without another task interfering.
776 asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist)
778 if (!capable(CAP_SETGID))
779 return -EPERM;
780 if ((unsigned) gidsetsize > NGROUPS)
781 return -EINVAL;
782 if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
783 return -EFAULT;
784 current->ngroups = gidsetsize;
785 return 0;
788 int in_group_p(gid_t grp)
790 if (grp != current->fsgid) {
791 int i = current->ngroups;
792 if (i) {
793 gid_t *groups = current->groups;
794 do {
795 if (*groups == grp)
796 goto out;
797 groups++;
798 i--;
799 } while (i);
801 return 0;
803 out:
804 return 1;
808 * This should really be a blocking read-write lock
809 * rather than a semaphore. Anybody want to implement
810 * one?
812 DECLARE_MUTEX(uts_sem);
814 asmlinkage long sys_newuname(struct new_utsname * name)
816 int errno = 0;
818 down(&uts_sem);
819 if (copy_to_user(name,&system_utsname,sizeof *name))
820 errno = -EFAULT;
821 up(&uts_sem);
822 return errno;
825 asmlinkage long sys_sethostname(char *name, int len)
827 int errno;
829 if (!capable(CAP_SYS_ADMIN))
830 return -EPERM;
831 if (len < 0 || len > __NEW_UTS_LEN)
832 return -EINVAL;
833 down(&uts_sem);
834 errno = -EFAULT;
835 if (!copy_from_user(system_utsname.nodename, name, len)) {
836 system_utsname.nodename[len] = 0;
837 errno = 0;
839 up(&uts_sem);
840 return errno;
843 asmlinkage long sys_gethostname(char *name, int len)
845 int i, errno;
847 if (len < 0)
848 return -EINVAL;
849 down(&uts_sem);
850 i = 1 + strlen(system_utsname.nodename);
851 if (i > len)
852 i = len;
853 errno = 0;
854 if (copy_to_user(name, system_utsname.nodename, i))
855 errno = -EFAULT;
856 up(&uts_sem);
857 return errno;
861 * Only setdomainname; getdomainname can be implemented by calling
862 * uname()
864 asmlinkage long sys_setdomainname(char *name, int len)
866 int errno;
868 if (!capable(CAP_SYS_ADMIN))
869 return -EPERM;
870 if (len < 0 || len > __NEW_UTS_LEN)
871 return -EINVAL;
873 down(&uts_sem);
874 errno = -EFAULT;
875 if (!copy_from_user(system_utsname.domainname, name, len)) {
876 errno = 0;
877 system_utsname.domainname[len] = 0;
879 up(&uts_sem);
880 return errno;
883 asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim)
885 if (resource >= RLIM_NLIMITS)
886 return -EINVAL;
887 else
888 return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
889 ? -EFAULT : 0;
892 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
894 struct rlimit new_rlim, *old_rlim;
896 if (resource >= RLIM_NLIMITS)
897 return -EINVAL;
898 if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
899 return -EFAULT;
900 if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0)
901 return -EINVAL;
902 old_rlim = current->rlim + resource;
903 if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
904 (new_rlim.rlim_max > old_rlim->rlim_max)) &&
905 !capable(CAP_SYS_RESOURCE))
906 return -EPERM;
907 if (resource == RLIMIT_NOFILE) {
908 if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
909 return -EPERM;
911 *old_rlim = new_rlim;
912 return 0;
916 * It would make sense to put struct rusage in the task_struct,
917 * except that would make the task_struct be *really big*. After
918 * task_struct gets moved into malloc'ed memory, it would
919 * make sense to do this. It will make moving the rest of the information
920 * a lot simpler! (Which we're not doing right now because we're not
921 * measuring them yet).
923 * This is SMP safe. Either we are called from sys_getrusage on ourselves
924 * below (we know we aren't going to exit/disappear and only we change our
925 * rusage counters), or we are called from wait4() on a process which is
926 * either stopped or zombied. In the zombied case the task won't get
927 * reaped till shortly after the call to getrusage(), in both cases the
928 * task being examined is in a frozen state so the counters won't change.
930 * FIXME! Get the fault counts properly!
932 int getrusage(struct task_struct *p, int who, struct rusage *ru)
934 struct rusage r;
936 memset((char *) &r, 0, sizeof(r));
937 switch (who) {
938 case RUSAGE_SELF:
939 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime);
940 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime);
941 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime);
942 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime);
943 r.ru_minflt = p->min_flt;
944 r.ru_majflt = p->maj_flt;
945 r.ru_nswap = p->nswap;
946 break;
947 case RUSAGE_CHILDREN:
948 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_cutime);
949 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_cutime);
950 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_cstime);
951 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_cstime);
952 r.ru_minflt = p->cmin_flt;
953 r.ru_majflt = p->cmaj_flt;
954 r.ru_nswap = p->cnswap;
955 break;
956 default:
957 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime + p->times.tms_cutime);
958 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime + p->times.tms_cutime);
959 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime + p->times.tms_cstime);
960 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime + p->times.tms_cstime);
961 r.ru_minflt = p->min_flt + p->cmin_flt;
962 r.ru_majflt = p->maj_flt + p->cmaj_flt;
963 r.ru_nswap = p->nswap + p->cnswap;
964 break;
966 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
969 asmlinkage long sys_getrusage(int who, struct rusage *ru)
971 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
972 return -EINVAL;
973 return getrusage(current, who, ru);
976 asmlinkage long sys_umask(int mask)
978 mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
979 return mask;
982 asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
983 unsigned long arg4, unsigned long arg5)
985 int error = 0;
986 int sig;
988 switch (option) {
989 case PR_SET_PDEATHSIG:
990 sig = arg2;
991 if (sig > _NSIG) {
992 error = -EINVAL;
993 break;
995 current->pdeath_signal = sig;
996 break;
997 case PR_GET_PDEATHSIG:
998 error = put_user(current->pdeath_signal, (int *)arg2);
999 break;
1000 case PR_GET_DUMPABLE:
1001 if (current->dumpable)
1002 error = 1;
1003 break;
1004 case PR_SET_DUMPABLE:
1005 if (arg2 != 0 && arg2 != 1) {
1006 error = -EINVAL;
1007 break;
1009 current->dumpable = arg2;
1010 break;
1011 default:
1012 error = -EINVAL;
1013 break;
1015 return error;