Import 2.1.36
[davej-history.git] / kernel / sys.c
blob934108fa83f855567e8874d243c1b6c1ab3e8c07
1 /*
2 * linux/kernel/sys.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
7 #include <linux/errno.h>
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/times.h>
11 #include <linux/utsname.h>
12 #include <linux/param.h>
13 #include <linux/resource.h>
14 #include <linux/signal.h>
15 #include <linux/string.h>
16 #include <linux/ptrace.h>
17 #include <linux/stat.h>
18 #include <linux/mman.h>
19 #include <linux/mm.h>
20 #include <linux/fcntl.h>
21 #include <linux/acct.h>
22 #include <linux/tty.h>
23 #include <linux/smp.h>
24 #include <linux/smp_lock.h>
25 #include <linux/notifier.h>
26 #include <linux/reboot.h>
28 #include <asm/uaccess.h>
29 #include <asm/io.h>
32 * this indicates whether you can reboot with ctrl-alt-del: the default is yes
35 int C_A_D = 1;
39 * Notifier list for kernel code which wants to be called
40 * at shutdown. This is used to stop any idling DMA operations
41 * and the like.
44 struct notifier_block *reboot_notifier_list = NULL;
46 int register_reboot_notifier(struct notifier_block * nb)
48 return notifier_chain_register(&reboot_notifier_list, nb);
51 int unregister_reboot_notifier(struct notifier_block * nb)
53 return notifier_chain_unregister(&reboot_notifier_list, nb);
58 extern void adjust_clock(void);
60 asmlinkage int sys_ni_syscall(void)
62 return -ENOSYS;
65 static int proc_sel(struct task_struct *p, int which, int who)
67 if(p->pid)
69 switch (which) {
70 case PRIO_PROCESS:
71 if (!who && p == current)
72 return 1;
73 return(p->pid == who);
74 case PRIO_PGRP:
75 if (!who)
76 who = current->pgrp;
77 return(p->pgrp == who);
78 case PRIO_USER:
79 if (!who)
80 who = current->uid;
81 return(p->uid == who);
84 return 0;
87 asmlinkage int sys_setpriority(int which, int who, int niceval)
89 struct task_struct *p;
90 unsigned int priority;
91 int error;
93 if (which > 2 || which < 0)
94 return -EINVAL;
96 /* normalize: avoid signed division (rounding problems) */
97 error = ESRCH;
98 priority = niceval;
99 if (niceval < 0)
100 priority = -niceval;
101 if (priority > 20)
102 priority = 20;
103 priority = (priority * DEF_PRIORITY + 10) / 20 + DEF_PRIORITY;
105 if (niceval >= 0) {
106 priority = 2*DEF_PRIORITY - priority;
107 if (!priority)
108 priority = 1;
111 read_lock(&tasklist_lock);
112 for_each_task(p) {
113 if (!proc_sel(p, which, who))
114 continue;
115 if (p->uid != current->euid &&
116 p->uid != current->uid && !suser()) {
117 error = EPERM;
118 continue;
120 if (error == ESRCH)
121 error = 0;
122 if (priority > p->priority && !suser())
123 error = EACCES;
124 else
125 p->priority = priority;
127 read_unlock(&tasklist_lock);
129 return -error;
133 * Ugh. To avoid negative return values, "getpriority()" will
134 * not return the normal nice-value, but a value that has been
135 * offset by 20 (ie it returns 0..40 instead of -20..20)
137 asmlinkage int sys_getpriority(int which, int who)
139 struct task_struct *p;
140 long max_prio = -ESRCH;
142 if (which > 2 || which < 0)
143 return -EINVAL;
145 read_lock(&tasklist_lock);
146 for_each_task (p) {
147 if (!proc_sel(p, which, who))
148 continue;
149 if (p->priority > max_prio)
150 max_prio = p->priority;
152 read_unlock(&tasklist_lock);
154 /* scale the priority from timeslice to 0..40 */
155 if (max_prio > 0)
156 max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY;
157 return max_prio;
160 #ifndef __alpha__
163 * Why do these exist? Binary compatibility with some other standard?
164 * If so, maybe they should be moved into the appropriate arch
165 * directory.
168 asmlinkage int sys_profil(void)
170 return -ENOSYS;
173 asmlinkage int sys_ftime(void)
175 return -ENOSYS;
178 asmlinkage int sys_break(void)
180 return -ENOSYS;
183 asmlinkage int sys_stty(void)
185 return -ENOSYS;
188 asmlinkage int sys_gtty(void)
190 return -ENOSYS;
193 asmlinkage int sys_prof(void)
195 return -ENOSYS;
198 #endif
200 extern asmlinkage int sys_kill(int, int);
203 * Reboot system call: for obvious reasons only root may call it,
204 * and even root needs to set up some magic numbers in the registers
205 * so that some mistake won't make this reboot the whole machine.
206 * You can also set the meaning of the ctrl-alt-del-key here.
208 * reboot doesn't sync: do that yourself before calling this.
211 asmlinkage int sys_reboot(int magic1, int magic2, int cmd, void * arg)
213 char buffer[256];
215 /* We only trust the superuser with rebooting the system. */
216 if (!suser())
217 return -EPERM;
219 /* For safety, we require "magic" arguments. */
220 if (magic1 != LINUX_REBOOT_MAGIC1 ||
221 (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A))
222 return -EINVAL;
224 lock_kernel();
225 switch (cmd) {
226 case LINUX_REBOOT_CMD_RESTART:
227 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
228 printk(KERN_EMERG "Restarting system.\n");
229 machine_restart(NULL);
230 break;
232 case LINUX_REBOOT_CMD_CAD_ON:
233 C_A_D = 1;
234 break;
236 case LINUX_REBOOT_CMD_CAD_OFF:
237 C_A_D = 0;
238 break;
240 case LINUX_REBOOT_CMD_HALT:
241 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
242 printk(KERN_EMERG "System halted.\n");
243 machine_halt();
244 do_exit(0);
245 break;
247 case LINUX_REBOOT_CMD_POWER_OFF:
248 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
249 printk(KERN_EMERG "Power down.\n");
250 machine_power_off();
251 do_exit(0);
252 break;
254 case LINUX_REBOOT_CMD_RESTART2:
255 if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) {
256 unlock_kernel();
257 return -EFAULT;
259 buffer[sizeof(buffer) - 1] = '\0';
261 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
262 printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
263 machine_restart(buffer);
264 break;
266 default:
267 unlock_kernel();
268 return -EINVAL;
269 break;
271 unlock_kernel();
272 return 0;
276 * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
277 * As it's called within an interrupt, it may NOT sync: the only choice
278 * is whether to reboot at once, or just ignore the ctrl-alt-del.
280 void ctrl_alt_del(void)
282 if (C_A_D) {
283 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
284 machine_restart(NULL);
285 } else
286 kill_proc(1, SIGINT, 1);
291 * Unprivileged users may change the real gid to the effective gid
292 * or vice versa. (BSD-style)
294 * If you set the real gid at all, or set the effective gid to a value not
295 * equal to the real gid, then the saved gid is set to the new effective gid.
297 * This makes it possible for a setgid program to completely drop its
298 * privileges, which is often a useful assertion to make when you are doing
299 * a security audit over a program.
301 * The general idea is that a program which uses just setregid() will be
302 * 100% compatible with BSD. A program which uses just setgid() will be
303 * 100% compatible with POSIX w/ Saved ID's.
305 * SMP: There are not races, the gid's are checked only by filesystem
306 * operations (as far as semantic preservation is concerned).
308 asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
310 int old_rgid = current->gid;
311 int old_egid = current->egid;
313 if (rgid != (gid_t) -1) {
314 if ((old_rgid == rgid) ||
315 (current->egid==rgid) ||
316 suser())
317 current->gid = rgid;
318 else
319 return -EPERM;
321 if (egid != (gid_t) -1) {
322 if ((old_rgid == egid) ||
323 (current->egid == egid) ||
324 (current->sgid == egid) ||
325 suser())
326 current->fsgid = current->egid = egid;
327 else {
328 current->gid = old_rgid;
329 return -EPERM;
332 if (rgid != (gid_t) -1 ||
333 (egid != (gid_t) -1 && egid != old_rgid))
334 current->sgid = current->egid;
335 current->fsgid = current->egid;
336 if (current->egid != old_egid)
337 current->dumpable = 0;
338 return 0;
342 * setgid() is implemented like SysV w/ SAVED_IDS
344 * SMP: Same implicit races as above.
346 asmlinkage int sys_setgid(gid_t gid)
348 int old_egid = current->egid;
350 if (suser())
351 current->gid = current->egid = current->sgid = current->fsgid = gid;
352 else if ((gid == current->gid) || (gid == current->sgid))
353 current->egid = current->fsgid = gid;
354 else
355 return -EPERM;
357 if (current->egid != old_egid)
358 current->dumpable = 0;
359 return 0;
362 static char acct_active = 0;
363 static struct file acct_file;
365 int acct_process(long exitcode)
367 struct acct ac;
368 unsigned short fs;
370 if (acct_active) {
371 strncpy(ac.ac_comm, current->comm, ACCT_COMM);
372 ac.ac_comm[ACCT_COMM-1] = '\0';
373 ac.ac_utime = current->utime;
374 ac.ac_stime = current->stime;
375 ac.ac_btime = CT_TO_SECS(current->start_time) + (xtime.tv_sec - (jiffies / HZ));
376 ac.ac_etime = CURRENT_TIME - ac.ac_btime;
377 ac.ac_uid = current->uid;
378 ac.ac_gid = current->gid;
379 ac.ac_tty = (current)->tty == NULL ? -1 :
380 kdev_t_to_nr(current->tty->device);
381 ac.ac_flag = 0;
382 if (current->flags & PF_FORKNOEXEC)
383 ac.ac_flag |= AFORK;
384 if (current->flags & PF_SUPERPRIV)
385 ac.ac_flag |= ASU;
386 if (current->flags & PF_DUMPCORE)
387 ac.ac_flag |= ACORE;
388 if (current->flags & PF_SIGNALED)
389 ac.ac_flag |= AXSIG;
390 ac.ac_minflt = current->min_flt;
391 ac.ac_majflt = current->maj_flt;
392 ac.ac_exitcode = exitcode;
394 /* Kernel segment override */
395 fs = get_fs();
396 set_fs(KERNEL_DS);
398 acct_file.f_op->write(acct_file.f_inode, &acct_file,
399 (char *)&ac, sizeof(struct acct));
401 set_fs(fs);
403 return 0;
406 asmlinkage int sys_acct(const char *name)
408 struct inode *inode = (struct inode *)0;
409 char *tmp;
410 int error = -EPERM;
412 lock_kernel();
413 if (!suser())
414 goto out;
416 if (name == (char *)0) {
417 if (acct_active) {
418 if (acct_file.f_op->release)
419 acct_file.f_op->release(acct_file.f_inode, &acct_file);
421 if (acct_file.f_inode != (struct inode *) 0)
422 iput(acct_file.f_inode);
424 acct_active = 0;
426 error = 0;
427 } else {
428 error = -EBUSY;
429 if (!acct_active) {
430 if ((error = getname(name, &tmp)) != 0)
431 goto out;
433 error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
434 putname(tmp);
435 if (error)
436 goto out;
438 error = -EACCES;
439 if (!S_ISREG(inode->i_mode)) {
440 iput(inode);
441 goto out;
444 error = -EIO;
445 if (!inode->i_op || !inode->i_op->default_file_ops ||
446 !inode->i_op->default_file_ops->write) {
447 iput(inode);
448 goto out;
451 acct_file.f_mode = 3;
452 acct_file.f_flags = 0;
453 acct_file.f_count = 1;
454 acct_file.f_inode = inode;
455 acct_file.f_pos = inode->i_size;
456 acct_file.f_reada = 0;
457 acct_file.f_op = inode->i_op->default_file_ops;
459 if(acct_file.f_op->open)
460 if(acct_file.f_op->open(acct_file.f_inode, &acct_file)) {
461 iput(inode);
462 goto out;
465 acct_active = 1;
466 error = 0;
469 out:
470 unlock_kernel();
471 return error;
474 #ifndef __alpha__
477 * Why do these exist? Binary compatibility with some other standard?
478 * If so, maybe they should be moved into the appropriate arch
479 * directory.
482 asmlinkage int sys_phys(void)
484 return -ENOSYS;
487 asmlinkage int sys_lock(void)
489 return -ENOSYS;
492 asmlinkage int sys_mpx(void)
494 return -ENOSYS;
497 asmlinkage int sys_ulimit(void)
499 return -ENOSYS;
502 asmlinkage int sys_old_syscall(void)
504 return -ENOSYS;
507 #endif
510 * Unprivileged users may change the real uid to the effective uid
511 * or vice versa. (BSD-style)
513 * If you set the real uid at all, or set the effective uid to a value not
514 * equal to the real uid, then the saved uid is set to the new effective uid.
516 * This makes it possible for a setuid program to completely drop its
517 * privileges, which is often a useful assertion to make when you are doing
518 * a security audit over a program.
520 * The general idea is that a program which uses just setreuid() will be
521 * 100% compatible with BSD. A program which uses just setuid() will be
522 * 100% compatible with POSIX w/ Saved ID's.
524 asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
526 int old_ruid;
527 int old_euid;
529 old_ruid = current->uid;
530 old_euid = current->euid;
531 if (ruid != (uid_t) -1) {
532 if ((old_ruid == ruid) ||
533 (current->euid==ruid) ||
534 suser())
535 current->uid = ruid;
536 else
537 return -EPERM;
539 if (euid != (uid_t) -1) {
540 if ((old_ruid == euid) ||
541 (current->euid == euid) ||
542 (current->suid == euid) ||
543 suser())
544 current->fsuid = current->euid = euid;
545 else {
546 current->uid = old_ruid;
547 return -EPERM;
550 if (ruid != (uid_t) -1 ||
551 (euid != (uid_t) -1 && euid != old_ruid))
552 current->suid = current->euid;
553 current->fsuid = current->euid;
554 if (current->euid != old_euid)
555 current->dumpable = 0;
556 return 0;
560 * setuid() is implemented like SysV w/ SAVED_IDS
562 * Note that SAVED_ID's is deficient in that a setuid root program
563 * like sendmail, for example, cannot set its uid to be a normal
564 * user and then switch back, because if you're root, setuid() sets
565 * the saved uid too. If you don't like this, blame the bright people
566 * in the POSIX committee and/or USG. Note that the BSD-style setreuid()
567 * will allow a root program to temporarily drop privileges and be able to
568 * regain them by swapping the real and effective uid.
570 asmlinkage int sys_setuid(uid_t uid)
572 int old_euid = current->euid;
574 if (suser())
575 current->uid = current->euid = current->suid = current->fsuid = uid;
576 else if ((uid == current->uid) || (uid == current->suid))
577 current->fsuid = current->euid = uid;
578 else
579 return -EPERM;
581 if (current->euid != old_euid)
582 current->dumpable = 0;
583 return 0;
588 * This function implementes a generic ability to update ruid, euid,
589 * and suid. This allows you to implement the 4.4 compatible seteuid().
591 asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
593 uid_t old_ruid, old_euid, old_suid;
595 old_ruid = current->uid;
596 old_euid = current->euid;
597 old_suid = current->suid;
599 if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
600 (ruid != current->euid) && (ruid != current->suid))
601 return -EPERM;
602 if ((euid != (uid_t) -1) && (euid != current->uid) &&
603 (euid != current->euid) && (euid != current->suid))
604 return -EPERM;
605 if ((suid != (uid_t) -1) && (suid != current->uid) &&
606 (suid != current->euid) && (suid != current->suid))
607 return -EPERM;
608 if (ruid != (uid_t) -1)
609 current->uid = ruid;
610 if (euid != (uid_t) -1)
611 current->euid = euid;
612 if (suid != (uid_t) -1)
613 current->suid = suid;
614 return 0;
617 asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
619 int retval;
621 if (!(retval = put_user(current->uid, ruid)) &&
622 !(retval = put_user(current->euid, euid)))
623 retval = put_user(current->suid, suid);
625 return retval;
630 * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
631 * is used for "access()" and for the NFS daemon (letting nfsd stay at
632 * whatever uid it wants to). It normally shadows "euid", except when
633 * explicitly set by setfsuid() or for access..
635 asmlinkage int sys_setfsuid(uid_t uid)
637 int old_fsuid;
639 old_fsuid = current->fsuid;
640 if (uid == current->uid || uid == current->euid ||
641 uid == current->suid || uid == current->fsuid || suser())
642 current->fsuid = uid;
643 if (current->fsuid != old_fsuid)
644 current->dumpable = 0;
646 return old_fsuid;
650 * Samma på svenska..
652 asmlinkage int sys_setfsgid(gid_t gid)
654 int old_fsgid;
656 old_fsgid = current->fsgid;
657 if (gid == current->gid || gid == current->egid ||
658 gid == current->sgid || gid == current->fsgid || suser())
659 current->fsgid = gid;
660 if (current->fsgid != old_fsgid)
661 current->dumpable = 0;
663 return old_fsgid;
666 asmlinkage long sys_times(struct tms * tbuf)
669 * In the SMP world we might just be unlucky and have one of
670 * the times increment as we use it. Since the value is an
671 * atomically safe type this is just fine. Conceptually its
672 * as if the syscall took an instant longer to occur.
674 if (tbuf)
676 /* ?? use copy_to_user() */
677 if(!access_ok(VERIFY_READ, tbuf, sizeof(struct tms)) ||
678 __put_user(current->utime,&tbuf->tms_utime)||
679 __put_user(current->stime,&tbuf->tms_stime) ||
680 __put_user(current->cutime,&tbuf->tms_cutime) ||
681 __put_user(current->cstime,&tbuf->tms_cstime))
682 return -EFAULT;
684 return jiffies;
688 * This needs some heavy checking ...
689 * I just haven't the stomach for it. I also don't fully
690 * understand sessions/pgrp etc. Let somebody who does explain it.
692 * OK, I think I have the protection semantics right.... this is really
693 * only important on a multi-user system anyway, to make sure one user
694 * can't send a signal to a process owned by another. -TYT, 12/12/91
696 * Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
697 * LBT 04.03.94
700 asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
702 struct task_struct * p;
703 int err = -EINVAL;
705 if (!pid)
706 pid = current->pid;
707 if (!pgid)
708 pgid = pid;
709 if (pgid < 0)
710 return -EINVAL;
712 read_lock(&tasklist_lock);
713 for_each_task(p) {
714 if (p->pid == pid) {
715 /* NOTE: I haven't dropped tasklist_lock, this is
716 * on purpose. -DaveM
718 goto found_task;
721 read_unlock(&tasklist_lock);
722 return -ESRCH;
724 found_task:
725 /* From this point forward we keep holding onto the tasklist lock
726 * so that our parent does not change from under us. -DaveM
728 err = -ESRCH;
729 if (p->p_pptr == current || p->p_opptr == current) {
730 err = -EPERM;
731 if (p->session != current->session)
732 goto out;
733 err = -EACCES;
734 if (p->did_exec)
735 goto out;
736 } else if (p != current)
737 goto out;
738 err = -EPERM;
739 if (p->leader)
740 goto out;
741 if (pgid != pid) {
742 struct task_struct * tmp;
743 for_each_task (tmp) {
744 if (tmp->pgrp == pgid &&
745 tmp->session == current->session)
746 goto ok_pgid;
748 goto out;
751 ok_pgid:
752 p->pgrp = pgid;
753 err = 0;
754 out:
755 /* All paths lead to here, thus we are safe. -DaveM */
756 read_unlock(&tasklist_lock);
757 return err;
760 asmlinkage int sys_getpgid(pid_t pid)
762 if (!pid) {
763 return current->pgrp;
764 } else {
765 struct task_struct *p;
766 int ret = -ESRCH;
768 read_lock(&tasklist_lock);
769 for_each_task(p) {
770 if (p->pid == pid) {
771 ret = p->pgrp;
772 break;
775 read_unlock(&tasklist_lock);
776 return ret;
780 asmlinkage int sys_getpgrp(void)
782 /* SMP - assuming writes are word atomic this is fine */
783 return current->pgrp;
786 asmlinkage int sys_getsid(pid_t pid)
788 struct task_struct * p;
789 int ret;
791 /* SMP: The 'self' case requires no lock */
792 if (!pid) {
793 ret = current->session;
794 } else {
795 ret = -ESRCH;
797 read_lock(&tasklist_lock);
798 for_each_task(p) {
799 if (p->pid == pid) {
800 ret = p->session;
801 break;
804 read_unlock(&tasklist_lock);
806 return ret;
809 asmlinkage int sys_setsid(void)
811 struct task_struct * p;
812 int err = -EPERM;
814 read_lock(&tasklist_lock);
815 for_each_task(p) {
816 if (p->pgrp == current->pid)
817 goto out;
820 current->leader = 1;
821 current->session = current->pgrp = current->pid;
822 current->tty = NULL;
823 current->tty_old_pgrp = 0;
824 err = current->pgrp;
825 out:
826 read_unlock(&tasklist_lock);
827 return err;
831 * Supplementary group ID's
833 asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
835 int i;
838 * SMP: Nobody else can change our grouplist. Thus we are
839 * safe.
842 if (gidsetsize < 0)
843 return -EINVAL;
844 i = current->ngroups;
845 if (gidsetsize) {
846 if (i > gidsetsize)
847 return -EINVAL;
848 if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i))
849 return -EFAULT;
851 return i;
855 * SMP: Our groups are not shared. We can copy to/from them safely
856 * without another task interfering.
859 asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
861 if (!suser())
862 return -EPERM;
863 if ((unsigned) gidsetsize > NGROUPS)
864 return -EINVAL;
865 if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
866 return -EFAULT;
867 current->ngroups = gidsetsize;
868 return 0;
871 int in_group_p(gid_t grp)
873 if (grp != current->fsgid) {
874 int i = current->ngroups;
875 if (i) {
876 gid_t *groups = current->groups;
877 do {
878 if (*groups == grp)
879 goto out;
880 groups++;
881 i--;
882 } while (i);
884 return 0;
886 out:
887 return 1;
890 asmlinkage int sys_newuname(struct new_utsname * name)
892 if (!name)
893 return -EFAULT;
894 if (copy_to_user(name,&system_utsname,sizeof *name))
895 return -EFAULT;
896 return 0;
899 #ifndef __alpha__
902 * Move these to arch dependent dir since they are for
903 * backward compatibility only?
906 #ifndef __sparc__
907 asmlinkage int sys_uname(struct old_utsname * name)
909 if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
910 return 0;
911 return -EFAULT;
913 #endif
915 asmlinkage int sys_olduname(struct oldold_utsname * name)
917 int error;
919 if (!name)
920 return -EFAULT;
921 if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
922 return -EFAULT;
924 error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
925 error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
926 error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
927 error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
928 error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
929 error -= __put_user(0,name->release+__OLD_UTS_LEN);
930 error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
931 error -= __put_user(0,name->version+__OLD_UTS_LEN);
932 error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
933 error = __put_user(0,name->machine+__OLD_UTS_LEN);
934 error = error ? -EFAULT : 0;
936 return error;
939 #endif
941 asmlinkage int sys_sethostname(char *name, int len)
943 if (!suser())
944 return -EPERM;
945 if (len < 0 || len > __NEW_UTS_LEN)
946 return -EINVAL;
947 if(copy_from_user(system_utsname.nodename, name, len))
948 return -EFAULT;
949 system_utsname.nodename[len] = 0;
950 return 0;
953 asmlinkage int sys_gethostname(char *name, int len)
955 int i;
957 if (len < 0)
958 return -EINVAL;
959 i = 1 + strlen(system_utsname.nodename);
960 if (i > len)
961 i = len;
962 return copy_to_user(name, system_utsname.nodename, i) ? -EFAULT : 0;
966 * Only setdomainname; getdomainname can be implemented by calling
967 * uname()
969 asmlinkage int sys_setdomainname(char *name, int len)
971 if (!suser())
972 return -EPERM;
973 if (len < 0 || len > __NEW_UTS_LEN)
974 return -EINVAL;
975 if(copy_from_user(system_utsname.domainname, name, len))
976 return -EFAULT;
977 system_utsname.domainname[len] = 0;
978 return 0;
981 asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
983 if (resource >= RLIM_NLIMITS)
984 return -EINVAL;
985 else
986 return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
987 ? -EFAULT : 0;
990 asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
992 struct rlimit new_rlim, *old_rlim;
994 if (resource >= RLIM_NLIMITS)
995 return -EINVAL;
996 if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
997 return -EFAULT;
998 old_rlim = current->rlim + resource;
999 if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
1000 (new_rlim.rlim_max > old_rlim->rlim_max)) &&
1001 !suser())
1002 return -EPERM;
1003 if (resource == RLIMIT_NOFILE) {
1004 if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
1005 return -EPERM;
1007 *old_rlim = new_rlim;
1008 return 0;
1012 * It would make sense to put struct rusage in the task_struct,
1013 * except that would make the task_struct be *really big*. After
1014 * task_struct gets moved into malloc'ed memory, it would
1015 * make sense to do this. It will make moving the rest of the information
1016 * a lot simpler! (Which we're not doing right now because we're not
1017 * measuring them yet).
1019 * This is SMP safe. Either we are called from sys_getrusage on ourselves
1020 * below (we know we aren't going to exit/disappear and only we change our
1021 * rusage counters), or we are called from wait4() on a process which is
1022 * either stopped or zombied. In the zombied case the task won't get
1023 * reaped till shortly after the call to getrusage(), in both cases the
1024 * task being examined is in a frozen state so the counters won't change.
1026 int getrusage(struct task_struct *p, int who, struct rusage *ru)
1028 struct rusage r;
1030 memset((char *) &r, 0, sizeof(r));
1031 switch (who) {
1032 case RUSAGE_SELF:
1033 r.ru_utime.tv_sec = CT_TO_SECS(p->utime);
1034 r.ru_utime.tv_usec = CT_TO_USECS(p->utime);
1035 r.ru_stime.tv_sec = CT_TO_SECS(p->stime);
1036 r.ru_stime.tv_usec = CT_TO_USECS(p->stime);
1037 r.ru_minflt = p->min_flt;
1038 r.ru_majflt = p->maj_flt;
1039 r.ru_nswap = p->nswap;
1040 break;
1041 case RUSAGE_CHILDREN:
1042 r.ru_utime.tv_sec = CT_TO_SECS(p->cutime);
1043 r.ru_utime.tv_usec = CT_TO_USECS(p->cutime);
1044 r.ru_stime.tv_sec = CT_TO_SECS(p->cstime);
1045 r.ru_stime.tv_usec = CT_TO_USECS(p->cstime);
1046 r.ru_minflt = p->cmin_flt;
1047 r.ru_majflt = p->cmaj_flt;
1048 r.ru_nswap = p->cnswap;
1049 break;
1050 default:
1051 r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime);
1052 r.ru_utime.tv_usec = CT_TO_USECS(p->utime + p->cutime);
1053 r.ru_stime.tv_sec = CT_TO_SECS(p->stime + p->cstime);
1054 r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime);
1055 r.ru_minflt = p->min_flt + p->cmin_flt;
1056 r.ru_majflt = p->maj_flt + p->cmaj_flt;
1057 r.ru_nswap = p->nswap + p->cnswap;
1058 break;
1060 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
1063 asmlinkage int sys_getrusage(int who, struct rusage *ru)
1065 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
1066 return -EINVAL;
1067 return getrusage(current, who, ru);
1070 asmlinkage int sys_umask(int mask)
1072 mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
1073 return mask;