Import 2.3.12pre9
[davej-history.git] / kernel / sys.c
blob9ab1b2f4ce009393afd386540147001ccf2c74ec
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);
46 extern void adjust_clock(void);
48 asmlinkage int sys_ni_syscall(void)
50 return -ENOSYS;
53 static int proc_sel(struct task_struct *p, int which, int who)
55 if(p->pid)
57 switch (which) {
58 case PRIO_PROCESS:
59 if (!who && p == current)
60 return 1;
61 return(p->pid == who);
62 case PRIO_PGRP:
63 if (!who)
64 who = current->pgrp;
65 return(p->pgrp == who);
66 case PRIO_USER:
67 if (!who)
68 who = current->uid;
69 return(p->uid == who);
72 return 0;
75 asmlinkage int sys_setpriority(int which, int who, int niceval)
77 struct task_struct *p;
78 unsigned int priority;
79 int error;
81 if (which > 2 || which < 0)
82 return -EINVAL;
84 /* normalize: avoid signed division (rounding problems) */
85 error = ESRCH;
86 priority = niceval;
87 if (niceval < 0)
88 priority = -niceval;
89 if (priority > 20)
90 priority = 20;
91 priority = (priority * DEF_PRIORITY + 10) / 20 + DEF_PRIORITY;
93 if (niceval >= 0) {
94 priority = 2*DEF_PRIORITY - priority;
95 if (!priority)
96 priority = 1;
99 read_lock(&tasklist_lock);
100 for_each_task(p) {
101 if (!proc_sel(p, which, who))
102 continue;
103 if (p->uid != current->euid &&
104 p->uid != current->uid && !capable(CAP_SYS_NICE)) {
105 error = EPERM;
106 continue;
108 if (error == ESRCH)
109 error = 0;
110 if (priority > p->priority && !capable(CAP_SYS_NICE))
111 error = EACCES;
112 else
113 p->priority = priority;
115 read_unlock(&tasklist_lock);
117 return -error;
121 * Ugh. To avoid negative return values, "getpriority()" will
122 * not return the normal nice-value, but a value that has been
123 * offset by 20 (ie it returns 0..40 instead of -20..20)
125 asmlinkage int sys_getpriority(int which, int who)
127 struct task_struct *p;
128 long max_prio = -ESRCH;
130 if (which > 2 || which < 0)
131 return -EINVAL;
133 read_lock(&tasklist_lock);
134 for_each_task (p) {
135 if (!proc_sel(p, which, who))
136 continue;
137 if (p->priority > max_prio)
138 max_prio = p->priority;
140 read_unlock(&tasklist_lock);
142 /* scale the priority from timeslice to 0..40 */
143 if (max_prio > 0)
144 max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY;
145 return max_prio;
150 * Reboot system call: for obvious reasons only root may call it,
151 * and even root needs to set up some magic numbers in the registers
152 * so that some mistake won't make this reboot the whole machine.
153 * You can also set the meaning of the ctrl-alt-del-key here.
155 * reboot doesn't sync: do that yourself before calling this.
157 asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg)
159 char buffer[256];
161 /* We only trust the superuser with rebooting the system. */
162 if (!capable(CAP_SYS_BOOT))
163 return -EPERM;
165 /* For safety, we require "magic" arguments. */
166 if (magic1 != LINUX_REBOOT_MAGIC1 ||
167 (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
168 magic2 != LINUX_REBOOT_MAGIC2B))
169 return -EINVAL;
171 lock_kernel();
172 switch (cmd) {
173 case LINUX_REBOOT_CMD_RESTART:
174 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
175 printk(KERN_EMERG "Restarting system.\n");
176 machine_restart(NULL);
177 break;
179 case LINUX_REBOOT_CMD_CAD_ON:
180 C_A_D = 1;
181 break;
183 case LINUX_REBOOT_CMD_CAD_OFF:
184 C_A_D = 0;
185 break;
187 case LINUX_REBOOT_CMD_HALT:
188 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
189 printk(KERN_EMERG "System halted.\n");
190 machine_halt();
191 do_exit(0);
192 break;
194 case LINUX_REBOOT_CMD_POWER_OFF:
195 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
196 printk(KERN_EMERG "Power down.\n");
197 machine_power_off();
198 do_exit(0);
199 break;
201 case LINUX_REBOOT_CMD_RESTART2:
202 if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) {
203 unlock_kernel();
204 return -EFAULT;
206 buffer[sizeof(buffer) - 1] = '\0';
208 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
209 printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
210 machine_restart(buffer);
211 break;
213 default:
214 unlock_kernel();
215 return -EINVAL;
216 break;
218 unlock_kernel();
219 return 0;
223 * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
224 * As it's called within an interrupt, it may NOT sync: the only choice
225 * is whether to reboot at once, or just ignore the ctrl-alt-del.
227 void ctrl_alt_del(void)
229 if (C_A_D) {
230 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
231 machine_restart(NULL);
232 } else
233 kill_proc(1, SIGINT, 1);
238 * Unprivileged users may change the real gid to the effective gid
239 * or vice versa. (BSD-style)
241 * If you set the real gid at all, or set the effective gid to a value not
242 * equal to the real gid, then the saved gid is set to the new effective gid.
244 * This makes it possible for a setgid program to completely drop its
245 * privileges, which is often a useful assertion to make when you are doing
246 * a security audit over a program.
248 * The general idea is that a program which uses just setregid() will be
249 * 100% compatible with BSD. A program which uses just setgid() will be
250 * 100% compatible with POSIX with saved IDs.
252 * SMP: There are not races, the GIDs are checked only by filesystem
253 * operations (as far as semantic preservation is concerned).
255 asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
257 int old_rgid = current->gid;
258 int old_egid = current->egid;
260 if (rgid != (gid_t) -1) {
261 if ((old_rgid == rgid) ||
262 (current->egid==rgid) ||
263 capable(CAP_SETGID))
264 current->gid = rgid;
265 else
266 return -EPERM;
268 if (egid != (gid_t) -1) {
269 if ((old_rgid == egid) ||
270 (current->egid == egid) ||
271 (current->sgid == egid) ||
272 capable(CAP_SETGID))
273 current->fsgid = current->egid = egid;
274 else {
275 current->gid = old_rgid;
276 return -EPERM;
279 if (rgid != (gid_t) -1 ||
280 (egid != (gid_t) -1 && egid != old_rgid))
281 current->sgid = current->egid;
282 current->fsgid = current->egid;
283 if (current->egid != old_egid)
284 current->dumpable = 0;
285 return 0;
289 * setgid() is implemented like SysV w/ SAVED_IDS
291 * SMP: Same implicit races as above.
293 asmlinkage int sys_setgid(gid_t gid)
295 int old_egid = current->egid;
297 if (capable(CAP_SETGID))
298 current->gid = current->egid = current->sgid = current->fsgid = gid;
299 else if ((gid == current->gid) || (gid == current->sgid))
300 current->egid = current->fsgid = gid;
301 else
302 return -EPERM;
304 if (current->egid != old_egid)
305 current->dumpable = 0;
306 return 0;
310 * cap_emulate_setxuid() fixes the effective / permitted capabilities of
311 * a process after a call to setuid, setreuid, or setresuid.
313 * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
314 * {r,e,s}uid != 0, the permitted and effective capabilities are
315 * cleared.
317 * 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
318 * capabilities of the process are cleared.
320 * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
321 * capabilities are set to the permitted capabilities.
323 * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
324 * never happen.
326 * -astor
328 extern inline void cap_emulate_setxuid(int old_ruid, int old_euid,
329 int old_suid)
331 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
332 (current->uid != 0 && current->euid != 0 && current->suid != 0)) {
333 cap_clear(current->cap_permitted);
334 cap_clear(current->cap_effective);
336 if (old_euid == 0 && current->euid != 0) {
337 cap_clear(current->cap_effective);
339 if (old_euid != 0 && current->euid == 0) {
340 current->cap_effective = current->cap_permitted;
345 * Unprivileged users may change the real uid to the effective uid
346 * or vice versa. (BSD-style)
348 * If you set the real uid at all, or set the effective uid to a value not
349 * equal to the real uid, then the saved uid is set to the new effective uid.
351 * This makes it possible for a setuid program to completely drop its
352 * privileges, which is often a useful assertion to make when you are doing
353 * a security audit over a program.
355 * The general idea is that a program which uses just setreuid() will be
356 * 100% compatible with BSD. A program which uses just setuid() will be
357 * 100% compatible with POSIX with saved IDs.
359 asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
361 int old_ruid, old_euid, old_suid, new_ruid;
363 new_ruid = old_ruid = current->uid;
364 old_euid = current->euid;
365 old_suid = current->suid;
366 if (ruid != (uid_t) -1) {
367 if ((old_ruid == ruid) ||
368 (current->euid==ruid) ||
369 capable(CAP_SETUID))
370 new_ruid = ruid;
371 else
372 return -EPERM;
374 if (euid != (uid_t) -1) {
375 if ((old_ruid == euid) ||
376 (current->euid == euid) ||
377 (current->suid == euid) ||
378 capable(CAP_SETUID))
379 current->fsuid = current->euid = euid;
380 else
381 return -EPERM;
383 if (ruid != (uid_t) -1 ||
384 (euid != (uid_t) -1 && euid != old_ruid))
385 current->suid = current->euid;
386 current->fsuid = current->euid;
387 if (current->euid != old_euid)
388 current->dumpable = 0;
390 if(new_ruid != old_ruid) {
391 /* What if a process setreuid()'s and this brings the
392 * new uid over his NPROC rlimit? We can check this now
393 * cheaply with the new uid cache, so if it matters
394 * we should be checking for it. -DaveM
396 free_uid(current);
397 current->uid = new_ruid;
398 alloc_uid(current);
401 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
402 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
405 return 0;
411 * setuid() is implemented like SysV with SAVED_IDS
413 * Note that SAVED_ID's is deficient in that a setuid root program
414 * like sendmail, for example, cannot set its uid to be a normal
415 * user and then switch back, because if you're root, setuid() sets
416 * the saved uid too. If you don't like this, blame the bright people
417 * in the POSIX committee and/or USG. Note that the BSD-style setreuid()
418 * will allow a root program to temporarily drop privileges and be able to
419 * regain them by swapping the real and effective uid.
421 asmlinkage int sys_setuid(uid_t uid)
423 int old_euid = current->euid;
424 int old_ruid, old_suid, new_ruid;
426 old_ruid = new_ruid = current->uid;
427 old_suid = current->suid;
428 if (capable(CAP_SETUID))
429 new_ruid = current->euid = current->suid = current->fsuid = uid;
430 else if ((uid == current->uid) || (uid == current->suid))
431 current->fsuid = current->euid = uid;
432 else
433 return -EPERM;
435 if (current->euid != old_euid)
436 current->dumpable = 0;
438 if (new_ruid != old_ruid) {
439 /* See comment above about NPROC rlimit issues... */
440 free_uid(current);
441 current->uid = new_ruid;
442 alloc_uid(current);
445 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
446 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
449 return 0;
454 * This function implements a generic ability to update ruid, euid,
455 * and suid. This allows you to implement the 4.4 compatible seteuid().
457 asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
459 int old_ruid = current->uid;
460 int old_euid = current->euid;
461 int old_suid = current->suid;
463 if (!capable(CAP_SETUID)) {
464 if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
465 (ruid != current->euid) && (ruid != current->suid))
466 return -EPERM;
467 if ((euid != (uid_t) -1) && (euid != current->uid) &&
468 (euid != current->euid) && (euid != current->suid))
469 return -EPERM;
470 if ((suid != (uid_t) -1) && (suid != current->uid) &&
471 (suid != current->euid) && (suid != current->suid))
472 return -EPERM;
474 if (ruid != (uid_t) -1) {
475 /* See above commentary about NPROC rlimit issues here. */
476 free_uid(current);
477 current->uid = ruid;
478 alloc_uid(current);
480 if (euid != (uid_t) -1) {
481 if (euid != current->euid)
482 current->dumpable = 0;
483 current->euid = euid;
484 current->fsuid = euid;
486 if (suid != (uid_t) -1)
487 current->suid = suid;
489 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
490 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
493 return 0;
496 asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
498 int retval;
500 if (!(retval = put_user(current->uid, ruid)) &&
501 !(retval = put_user(current->euid, euid)))
502 retval = put_user(current->suid, suid);
504 return retval;
508 * Same as above, but for rgid, egid, sgid.
510 asmlinkage int sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
512 if (!capable(CAP_SETGID)) {
513 if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
514 (rgid != current->egid) && (rgid != current->sgid))
515 return -EPERM;
516 if ((egid != (gid_t) -1) && (egid != current->gid) &&
517 (egid != current->egid) && (egid != current->sgid))
518 return -EPERM;
519 if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
520 (sgid != current->egid) && (sgid != current->sgid))
521 return -EPERM;
523 if (rgid != (gid_t) -1)
524 current->gid = rgid;
525 if (egid != (gid_t) -1) {
526 if (egid != current->egid)
527 current->dumpable = 0;
528 current->egid = egid;
529 current->fsgid = egid;
531 if (sgid != (gid_t) -1)
532 current->sgid = sgid;
533 return 0;
536 asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
538 int retval;
540 if (!(retval = put_user(current->gid, rgid)) &&
541 !(retval = put_user(current->egid, egid)))
542 retval = put_user(current->sgid, sgid);
544 return retval;
549 * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
550 * is used for "access()" and for the NFS daemon (letting nfsd stay at
551 * whatever uid it wants to). It normally shadows "euid", except when
552 * explicitly set by setfsuid() or for access..
554 asmlinkage int sys_setfsuid(uid_t uid)
556 int old_fsuid;
558 old_fsuid = current->fsuid;
559 if (uid == current->uid || uid == current->euid ||
560 uid == current->suid || uid == current->fsuid ||
561 capable(CAP_SETUID))
562 current->fsuid = uid;
563 if (current->fsuid != old_fsuid)
564 current->dumpable = 0;
566 /* We emulate fsuid by essentially doing a scaled-down version
567 * of what we did in setresuid and friends. However, we only
568 * operate on the fs-specific bits of the process' effective
569 * capabilities
571 * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
572 * if not, we might be a bit too harsh here.
575 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
576 if (old_fsuid == 0 && current->fsuid != 0) {
577 cap_t(current->cap_effective) &= ~CAP_FS_MASK;
579 if (old_fsuid != 0 && current->fsuid == 0) {
580 cap_t(current->cap_effective) |=
581 (cap_t(current->cap_permitted) & CAP_FS_MASK);
585 return old_fsuid;
589 * Samma på svenska..
591 asmlinkage int sys_setfsgid(gid_t gid)
593 int old_fsgid;
595 old_fsgid = current->fsgid;
596 if (gid == current->gid || gid == current->egid ||
597 gid == current->sgid || gid == current->fsgid ||
598 capable(CAP_SETGID))
599 current->fsgid = gid;
600 if (current->fsgid != old_fsgid)
601 current->dumpable = 0;
603 return old_fsgid;
606 asmlinkage long sys_times(struct tms * tbuf)
609 * In the SMP world we might just be unlucky and have one of
610 * the times increment as we use it. Since the value is an
611 * atomically safe type this is just fine. Conceptually its
612 * as if the syscall took an instant longer to occur.
614 if (tbuf)
615 if (copy_to_user(tbuf, &current->times, sizeof(struct tms)))
616 return -EFAULT;
617 return jiffies;
621 * This needs some heavy checking ...
622 * I just haven't the stomach for it. I also don't fully
623 * understand sessions/pgrp etc. Let somebody who does explain it.
625 * OK, I think I have the protection semantics right.... this is really
626 * only important on a multi-user system anyway, to make sure one user
627 * can't send a signal to a process owned by another. -TYT, 12/12/91
629 * Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
630 * LBT 04.03.94
633 asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
635 struct task_struct * p;
636 int err = -EINVAL;
638 if (!pid)
639 pid = current->pid;
640 if (!pgid)
641 pgid = pid;
642 if (pgid < 0)
643 return -EINVAL;
645 /* From this point forward we keep holding onto the tasklist lock
646 * so that our parent does not change from under us. -DaveM
648 read_lock(&tasklist_lock);
650 err = -ESRCH;
651 p = find_task_by_pid(pid);
652 if (!p)
653 goto out;
655 if (p->p_pptr == current || p->p_opptr == current) {
656 err = -EPERM;
657 if (p->session != current->session)
658 goto out;
659 err = -EACCES;
660 if (p->did_exec)
661 goto out;
662 } else if (p != current)
663 goto out;
664 err = -EPERM;
665 if (p->leader)
666 goto out;
667 if (pgid != pid) {
668 struct task_struct * tmp;
669 for_each_task (tmp) {
670 if (tmp->pgrp == pgid &&
671 tmp->session == current->session)
672 goto ok_pgid;
674 goto out;
677 ok_pgid:
678 p->pgrp = pgid;
679 err = 0;
680 out:
681 /* All paths lead to here, thus we are safe. -DaveM */
682 read_unlock(&tasklist_lock);
683 return err;
686 asmlinkage int sys_getpgid(pid_t pid)
688 if (!pid) {
689 return current->pgrp;
690 } else {
691 int retval;
692 struct task_struct *p;
694 read_lock(&tasklist_lock);
695 p = find_task_by_pid(pid);
697 retval = -ESRCH;
698 if (p)
699 retval = p->pgrp;
700 read_unlock(&tasklist_lock);
701 return retval;
705 asmlinkage int sys_getpgrp(void)
707 /* SMP - assuming writes are word atomic this is fine */
708 return current->pgrp;
711 asmlinkage int sys_getsid(pid_t pid)
713 if (!pid) {
714 return current->session;
715 } else {
716 int retval;
717 struct task_struct *p;
719 read_lock(&tasklist_lock);
720 p = find_task_by_pid(pid);
722 retval = -ESRCH;
723 if(p)
724 retval = p->session;
725 read_unlock(&tasklist_lock);
726 return retval;
730 asmlinkage int sys_setsid(void)
732 struct task_struct * p;
733 int err = -EPERM;
735 read_lock(&tasklist_lock);
736 for_each_task(p) {
737 if (p->pgrp == current->pid)
738 goto out;
741 current->leader = 1;
742 current->session = current->pgrp = current->pid;
743 current->tty = NULL;
744 current->tty_old_pgrp = 0;
745 err = current->pgrp;
746 out:
747 read_unlock(&tasklist_lock);
748 return err;
752 * Supplementary group IDs
754 asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
756 int i;
759 * SMP: Nobody else can change our grouplist. Thus we are
760 * safe.
763 if (gidsetsize < 0)
764 return -EINVAL;
765 i = current->ngroups;
766 if (gidsetsize) {
767 if (i > gidsetsize)
768 return -EINVAL;
769 if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i))
770 return -EFAULT;
772 return i;
776 * SMP: Our groups are not shared. We can copy to/from them safely
777 * without another task interfering.
780 asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
782 if (!capable(CAP_SETGID))
783 return -EPERM;
784 if ((unsigned) gidsetsize > NGROUPS)
785 return -EINVAL;
786 if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
787 return -EFAULT;
788 current->ngroups = gidsetsize;
789 return 0;
792 int in_group_p(gid_t grp)
794 if (grp != current->fsgid) {
795 int i = current->ngroups;
796 if (i) {
797 gid_t *groups = current->groups;
798 do {
799 if (*groups == grp)
800 goto out;
801 groups++;
802 i--;
803 } while (i);
805 return 0;
807 out:
808 return 1;
812 * This should really be a blocking read-write lock
813 * rather than a semaphore. Anybody want to implement
814 * one?
816 DECLARE_MUTEX(uts_sem);
818 asmlinkage int sys_newuname(struct new_utsname * name)
820 int errno = 0;
822 down(&uts_sem);
823 if (copy_to_user(name,&system_utsname,sizeof *name))
824 errno = -EFAULT;
825 up(&uts_sem);
826 return errno;
829 asmlinkage int sys_sethostname(char *name, int len)
831 int errno;
833 if (!capable(CAP_SYS_ADMIN))
834 return -EPERM;
835 if (len < 0 || len > __NEW_UTS_LEN)
836 return -EINVAL;
837 down(&uts_sem);
838 errno = -EFAULT;
839 if (!copy_from_user(system_utsname.nodename, name, len)) {
840 system_utsname.nodename[len] = 0;
841 errno = 0;
843 up(&uts_sem);
844 return errno;
847 asmlinkage int sys_gethostname(char *name, int len)
849 int i, errno;
851 if (len < 0)
852 return -EINVAL;
853 down(&uts_sem);
854 i = 1 + strlen(system_utsname.nodename);
855 if (i > len)
856 i = len;
857 errno = 0;
858 if (copy_to_user(name, system_utsname.nodename, i))
859 errno = -EFAULT;
860 up(&uts_sem);
861 return errno;
865 * Only setdomainname; getdomainname can be implemented by calling
866 * uname()
868 asmlinkage int sys_setdomainname(char *name, int len)
870 int errno;
872 if (!capable(CAP_SYS_ADMIN))
873 return -EPERM;
874 if (len < 0 || len > __NEW_UTS_LEN)
875 return -EINVAL;
877 down(&uts_sem);
878 errno = -EFAULT;
879 if (!copy_from_user(system_utsname.domainname, name, len)) {
880 errno = 0;
881 system_utsname.domainname[len] = 0;
883 up(&uts_sem);
884 return errno;
887 asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
889 if (resource >= RLIM_NLIMITS)
890 return -EINVAL;
891 else
892 return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
893 ? -EFAULT : 0;
896 asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
898 struct rlimit new_rlim, *old_rlim;
900 if (resource >= RLIM_NLIMITS)
901 return -EINVAL;
902 if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
903 return -EFAULT;
904 if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0)
905 return -EINVAL;
906 old_rlim = current->rlim + resource;
907 if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
908 (new_rlim.rlim_max > old_rlim->rlim_max)) &&
909 !capable(CAP_SYS_RESOURCE))
910 return -EPERM;
911 if (resource == RLIMIT_NOFILE) {
912 if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
913 return -EPERM;
915 *old_rlim = new_rlim;
916 return 0;
920 * It would make sense to put struct rusage in the task_struct,
921 * except that would make the task_struct be *really big*. After
922 * task_struct gets moved into malloc'ed memory, it would
923 * make sense to do this. It will make moving the rest of the information
924 * a lot simpler! (Which we're not doing right now because we're not
925 * measuring them yet).
927 * This is SMP safe. Either we are called from sys_getrusage on ourselves
928 * below (we know we aren't going to exit/disappear and only we change our
929 * rusage counters), or we are called from wait4() on a process which is
930 * either stopped or zombied. In the zombied case the task won't get
931 * reaped till shortly after the call to getrusage(), in both cases the
932 * task being examined is in a frozen state so the counters won't change.
934 * FIXME! Get the fault counts properly!
936 int getrusage(struct task_struct *p, int who, struct rusage *ru)
938 struct rusage r;
940 memset((char *) &r, 0, sizeof(r));
941 switch (who) {
942 case RUSAGE_SELF:
943 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime);
944 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime);
945 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime);
946 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime);
947 r.ru_minflt = p->min_flt;
948 r.ru_majflt = p->maj_flt;
949 r.ru_nswap = p->nswap;
950 break;
951 case RUSAGE_CHILDREN:
952 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_cutime);
953 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_cutime);
954 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_cstime);
955 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_cstime);
956 r.ru_minflt = p->cmin_flt;
957 r.ru_majflt = p->cmaj_flt;
958 r.ru_nswap = p->cnswap;
959 break;
960 default:
961 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime + p->times.tms_cutime);
962 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime + p->times.tms_cutime);
963 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime + p->times.tms_cstime);
964 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime + p->times.tms_cstime);
965 r.ru_minflt = p->min_flt + p->cmin_flt;
966 r.ru_majflt = p->maj_flt + p->cmaj_flt;
967 r.ru_nswap = p->nswap + p->cnswap;
968 break;
970 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
973 asmlinkage int sys_getrusage(int who, struct rusage *ru)
975 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
976 return -EINVAL;
977 return getrusage(current, who, ru);
980 asmlinkage int sys_umask(int mask)
982 mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
983 return mask;
986 asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
987 unsigned long arg4, unsigned long arg5)
989 int error = 0;
990 int sig;
992 switch (option) {
993 case PR_SET_PDEATHSIG:
994 sig = arg2;
995 if (sig > _NSIG) {
996 error = -EINVAL;
997 break;
999 current->pdeath_signal = sig;
1000 break;
1001 default:
1002 error = -EINVAL;
1003 break;
1005 return error;