Version:
~ [ 0.6-2.3.46 ] ~
Architecture:
~ [ um ] ~
** Warning: Cannot open xref database.
1 /*
2 * linux/kernel/sys.c
3 *
4 * Copyright (C) 1991, 1992 Linus Torvalds
5 */
6
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>
15 #include <linux/highuid.h>
16
17 #include <asm/uaccess.h>
18 #include <asm/io.h>
19
20 /*
21 * this is where the system-wide overflow UID and GID are defined, for
22 * architectures that now have 32-bit UID/GID but didn't in the past
23 */
24
25 int overflowuid = DEFAULT_OVERFLOWUID;
26 int overflowgid = DEFAULT_OVERFLOWGID;
27
28 /*
29 * the same as above, but for filesystems which can only store a 16-bit
30 * UID and GID. as such, this is needed on all architectures
31 */
32
33 int fs_overflowuid = DEFAULT_FS_OVERFLOWUID;
34 int fs_overflowgid = DEFAULT_FS_OVERFLOWUID;
35
36 /*
37 * this indicates whether you can reboot with ctrl-alt-del: the default is yes
38 */
39
40 int C_A_D = 1;
41
42
43 /*
44 * Notifier list for kernel code which wants to be called
45 * at shutdown. This is used to stop any idling DMA operations
46 * and the like.
47 */
48
49 struct notifier_block *reboot_notifier_list = NULL;
50
51 int register_reboot_notifier(struct notifier_block * nb)
52 {
53 return notifier_chain_register(&reboot_notifier_list, nb);
54 }
55
56 int unregister_reboot_notifier(struct notifier_block * nb)
57 {
58 return notifier_chain_unregister(&reboot_notifier_list, nb);
59 }
60
61 asmlinkage long sys_ni_syscall(void)
62 {
63 return -ENOSYS;
64 }
65
66 static int proc_sel(struct task_struct *p, int which, int who)
67 {
68 if(p->pid)
69 {
70 switch (which) {
71 case PRIO_PROCESS:
72 if (!who && p == current)
73 return 1;
74 return(p->pid == who);
75 case PRIO_PGRP:
76 if (!who)
77 who = current->pgrp;
78 return(p->pgrp == who);
79 case PRIO_USER:
80 if (!who)
81 who = current->uid;
82 return(p->uid == who);
83 }
84 }
85 return 0;
86 }
87
88 asmlinkage long sys_setpriority(int which, int who, int niceval)
89 {
90 struct task_struct *p;
91 unsigned int priority;
92 int error;
93
94 if (which > 2 || which < 0)
95 return -EINVAL;
96
97 /* normalize: avoid signed division (rounding problems) */
98 error = ESRCH;
99 priority = niceval;
100 if (niceval < 0)
101 priority = -niceval;
102 if (priority > 20)
103 priority = 20;
104 priority = (priority * DEF_PRIORITY + 10) / 20 + DEF_PRIORITY;
105
106 if (niceval >= 0) {
107 priority = 2*DEF_PRIORITY - priority;
108 if (!priority)
109 priority = 1;
110 }
111
112 read_lock(&tasklist_lock);
113 for_each_task(p) {
114 if (!proc_sel(p, which, who))
115 continue;
116 if (p->uid != current->euid &&
117 p->uid != current->uid && !capable(CAP_SYS_NICE)) {
118 error = EPERM;
119 continue;
120 }
121 if (error == ESRCH)
122 error = 0;
123 if (priority > p->priority && !capable(CAP_SYS_NICE))
124 error = EACCES;
125 else
126 p->priority = priority;
127 }
128 read_unlock(&tasklist_lock);
129
130 return -error;
131 }
132
133 /*
134 * Ugh. To avoid negative return values, "getpriority()" will
135 * not return the normal nice-value, but a value that has been
136 * offset by 20 (ie it returns 0..40 instead of -20..20)
137 */
138 asmlinkage long sys_getpriority(int which, int who)
139 {
140 struct task_struct *p;
141 long max_prio = -ESRCH;
142
143 if (which > 2 || which < 0)
144 return -EINVAL;
145
146 read_lock(&tasklist_lock);
147 for_each_task (p) {
148 if (!proc_sel(p, which, who))
149 continue;
150 if (p->priority > max_prio)
151 max_prio = p->priority;
152 }
153 read_unlock(&tasklist_lock);
154
155 /* scale the priority from timeslice to 0..40 */
156 if (max_prio > 0)
157 max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY;
158 return max_prio;
159 }
160
161
162 /*
163 * Reboot system call: for obvious reasons only root may call it,
164 * and even root needs to set up some magic numbers in the registers
165 * so that some mistake won't make this reboot the whole machine.
166 * You can also set the meaning of the ctrl-alt-del-key here.
167 *
168 * reboot doesn't sync: do that yourself before calling this.
169 */
170 asmlinkage long sys_reboot(int magic1, int magic2, int cmd, void * arg)
171 {
172 char buffer[256];
173
174 /* We only trust the superuser with rebooting the system. */
175 if (!capable(CAP_SYS_BOOT))
176 return -EPERM;
177
178 /* For safety, we require "magic" arguments. */
179 if (magic1 != LINUX_REBOOT_MAGIC1 ||
180 (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
181 magic2 != LINUX_REBOOT_MAGIC2B))
182 return -EINVAL;
183
184 lock_kernel();
185 switch (cmd) {
186 case LINUX_REBOOT_CMD_RESTART:
187 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
188 printk(KERN_EMERG "Restarting system.\n");
189 machine_restart(NULL);
190 break;
191
192 case LINUX_REBOOT_CMD_CAD_ON:
193 C_A_D = 1;
194 break;
195
196 case LINUX_REBOOT_CMD_CAD_OFF:
197 C_A_D = 0;
198 break;
199
200 case LINUX_REBOOT_CMD_HALT:
201 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
202 printk(KERN_EMERG "System halted.\n");
203 machine_halt();
204 do_exit(0);
205 break;
206
207 case LINUX_REBOOT_CMD_POWER_OFF:
208 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
209 printk(KERN_EMERG "Power down.\n");
210 machine_power_off();
211 do_exit(0);
212 break;
213
214 case LINUX_REBOOT_CMD_RESTART2:
215 if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) {
216 unlock_kernel();
217 return -EFAULT;
218 }
219 buffer[sizeof(buffer) - 1] = '\0';
220
221 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
222 printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
223 machine_restart(buffer);
224 break;
225
226 default:
227 unlock_kernel();
228 return -EINVAL;
229 break;
230 };
231 unlock_kernel();
232 return 0;
233 }
234
235 /*
236 * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
237 * As it's called within an interrupt, it may NOT sync: the only choice
238 * is whether to reboot at once, or just ignore the ctrl-alt-del.
239 */
240 void ctrl_alt_del(void)
241 {
242 if (C_A_D) {
243 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
244 machine_restart(NULL);
245 } else
246 kill_proc(1, SIGINT, 1);
247 }
248
249
250 /*
251 * Unprivileged users may change the real gid to the effective gid
252 * or vice versa. (BSD-style)
253 *
254 * If you set the real gid at all, or set the effective gid to a value not
255 * equal to the real gid, then the saved gid is set to the new effective gid.
256 *
257 * This makes it possible for a setgid program to completely drop its
258 * privileges, which is often a useful assertion to make when you are doing
259 * a security audit over a program.
260 *
261 * The general idea is that a program which uses just setregid() will be
262 * 100% compatible with BSD. A program which uses just setgid() will be
263 * 100% compatible with POSIX with saved IDs.
264 *
265 * SMP: There are not races, the GIDs are checked only by filesystem
266 * operations (as far as semantic preservation is concerned).
267 */
268 asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
269 {
270 int old_rgid = current->gid;
271 int old_egid = current->egid;
272
273 if (rgid != (gid_t) -1) {
274 if ((old_rgid == rgid) ||
275 (current->egid==rgid) ||
276 capable(CAP_SETGID))
277 current->gid = rgid;
278 else
279 return -EPERM;
280 }
281 if (egid != (gid_t) -1) {
282 if ((old_rgid == egid) ||
283 (current->egid == egid) ||
284 (current->sgid == egid) ||
285 capable(CAP_SETGID))
286 current->fsgid = current->egid = egid;
287 else {
288 current->gid = old_rgid;
289 return -EPERM;
290 }
291 }
292 if (rgid != (gid_t) -1 ||
293 (egid != (gid_t) -1 && egid != old_rgid))
294 current->sgid = current->egid;
295 current->fsgid = current->egid;
296 if (current->egid != old_egid)
297 current->dumpable = 0;
298 return 0;
299 }
300
301 /*
302 * setgid() is implemented like SysV w/ SAVED_IDS
303 *
304 * SMP: Same implicit races as above.
305 */
306 asmlinkage long sys_setgid(gid_t gid)
307 {
308 int old_egid = current->egid;
309
310 if (capable(CAP_SETGID))
311 current->gid = current->egid = current->sgid = current->fsgid = gid;
312 else if ((gid == current->gid) || (gid == current->sgid))
313 current->egid = current->fsgid = gid;
314 else
315 return -EPERM;
316
317 if (current->egid != old_egid)
318 current->dumpable = 0;
319 return 0;
320 }
321
322 /*
323 * cap_emulate_setxuid() fixes the effective / permitted capabilities of
324 * a process after a call to setuid, setreuid, or setresuid.
325 *
326 * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
327 * {r,e,s}uid != 0, the permitted and effective capabilities are
328 * cleared.
329 *
330 * 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
331 * capabilities of the process are cleared.
332 *
333 * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
334 * capabilities are set to the permitted capabilities.
335 *
336 * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
337 * never happen.
338 *
339 * -astor
340 */
341 extern inline void cap_emulate_setxuid(int old_ruid, int old_euid,
342 int old_suid)
343 {
344 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
345 (current->uid != 0 && current->euid != 0 && current->suid != 0)) {
346 cap_clear(current->cap_permitted);
347 cap_clear(current->cap_effective);
348 }
349 if (old_euid == 0 && current->euid != 0) {
350 cap_clear(current->cap_effective);
351 }
352 if (old_euid != 0 && current->euid == 0) {
353 current->cap_effective = current->cap_permitted;
354 }
355 }
356
357 /*
358 * Unprivileged users may change the real uid to the effective uid
359 * or vice versa. (BSD-style)
360 *
361 * If you set the real uid at all, or set the effective uid to a value not
362 * equal to the real uid, then the saved uid is set to the new effective uid.
363 *
364 * This makes it possible for a setuid program to completely drop its
365 * privileges, which is often a useful assertion to make when you are doing
366 * a security audit over a program.
367 *
368 * The general idea is that a program which uses just setreuid() will be
369 * 100% compatible with BSD. A program which uses just setuid() will be
370 * 100% compatible with POSIX with saved IDs.
371 */
372 asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
373 {
374 int old_ruid, old_euid, old_suid, new_ruid;
375
376 new_ruid = old_ruid = current->uid;
377 old_euid = current->euid;
378 old_suid = current->suid;
379 if (ruid != (uid_t) -1) {
380 if ((old_ruid == ruid) ||
381 (current->euid==ruid) ||
382 capable(CAP_SETUID))
383 new_ruid = ruid;
384 else
385 return -EPERM;
386 }
387 if (euid != (uid_t) -1) {
388 if ((old_ruid == euid) ||
389 (current->euid == euid) ||
390 (current->suid == euid) ||
391 capable(CAP_SETUID))
392 current->fsuid = current->euid = euid;
393 else
394 return -EPERM;
395 }
396 if (ruid != (uid_t) -1 ||
397 (euid != (uid_t) -1 && euid != old_ruid))
398 current->suid = current->euid;
399 current->fsuid = current->euid;
400 if (current->euid != old_euid)
401 current->dumpable = 0;
402
403 if(new_ruid != old_ruid) {
404 /* What if a process setreuid()'s and this brings the
405 * new uid over his NPROC rlimit? We can check this now
406 * cheaply with the new uid cache, so if it matters
407 * we should be checking for it. -DaveM
408 */
409 free_uid(current);
410 current->uid = new_ruid;
411 alloc_uid(current);
412 }
413
414 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
415 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
416 }
417
418 return 0;
419 }
420
421
422
423 /*
424 * setuid() is implemented like SysV with SAVED_IDS
425 *
426 * Note that SAVED_ID's is deficient in that a setuid root program
427 * like sendmail, for example, cannot set its uid to be a normal
428 * user and then switch back, because if you're root, setuid() sets
429 * the saved uid too. If you don't like this, blame the bright people
430 * in the POSIX committee and/or USG. Note that the BSD-style setreuid()
431 * will allow a root program to temporarily drop privileges and be able to
432 * regain them by swapping the real and effective uid.
433 */
434 asmlinkage long sys_setuid(uid_t uid)
435 {
436 int old_euid = current->euid;
437 int old_ruid, old_suid, new_ruid;
438
439 old_ruid = new_ruid = current->uid;
440 old_suid = current->suid;
441 if (capable(CAP_SETUID))
442 new_ruid = current->euid = current->suid = current->fsuid = uid;
443 else if ((uid == current->uid) || (uid == current->suid))
444 current->fsuid = current->euid = uid;
445 else
446 return -EPERM;
447
448 if (current->euid != old_euid)
449 current->dumpable = 0;
450
451 if (new_ruid != old_ruid) {
452 /* See comment above about NPROC rlimit issues... */
453 free_uid(current);
454 current->uid = new_ruid;
455 alloc_uid(current);
456 }
457
458 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
459 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
460 }
461
462 return 0;
463 }
464
465
466 /*
467 * This function implements a generic ability to update ruid, euid,
468 * and suid. This allows you to implement the 4.4 compatible seteuid().
469 */
470 asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
471 {
472 int old_ruid = current->uid;
473 int old_euid = current->euid;
474 int old_suid = current->suid;
475
476 if (!capable(CAP_SETUID)) {
477 if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
478 (ruid != current->euid) && (ruid != current->suid))
479 return -EPERM;
480 if ((euid != (uid_t) -1) && (euid != current->uid) &&
481 (euid != current->euid) && (euid != current->suid))
482 return -EPERM;
483 if ((suid != (uid_t) -1) && (suid != current->uid) &&
484 (suid != current->euid) && (suid != current->suid))
485 return -EPERM;
486 }
487 if (ruid != (uid_t) -1) {
488 /* See above commentary about NPROC rlimit issues here. */
489 free_uid(current);
490 current->uid = ruid;
491 alloc_uid(current);
492 }
493 if (euid != (uid_t) -1) {
494 if (euid != current->euid)
495 current->dumpable = 0;
496 current->euid = euid;
497 current->fsuid = euid;
498 }
499 if (suid != (uid_t) -1)
500 current->suid = suid;
501
502 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
503 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
504 }
505
506 return 0;
507 }
508
509 asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
510 {
511 int retval;
512
513 if (!(retval = put_user(current->uid, ruid)) &&
514 !(retval = put_user(current->euid, euid)))
515 retval = put_user(current->suid, suid);
516
517 return retval;
518 }
519
520 /*
521 * Same as above, but for rgid, egid, sgid.
522 */
523 asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
524 {
525 if (!capable(CAP_SETGID)) {
526 if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
527 (rgid != current->egid) && (rgid != current->sgid))
528 return -EPERM;
529 if ((egid != (gid_t) -1) && (egid != current->gid) &&
530 (egid != current->egid) && (egid != current->sgid))
531 return -EPERM;
532 if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
533 (sgid != current->egid) && (sgid != current->sgid))
534 return -EPERM;
535 }
536 if (rgid != (gid_t) -1)
537 current->gid = rgid;
538 if (egid != (gid_t) -1) {
539 if (egid != current->egid)
540 current->dumpable = 0;
541 current->egid = egid;
542 current->fsgid = egid;
543 }
544 if (sgid != (gid_t) -1)
545 current->sgid = sgid;
546 return 0;
547 }
548
549 asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
550 {
551 int retval;
552
553 if (!(retval = put_user(current->gid, rgid)) &&
554 !(retval = put_user(current->egid, egid)))
555 retval = put_user(current->sgid, sgid);
556
557 return retval;
558 }
559
560
561 /*
562 * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
563 * is used for "access()" and for the NFS daemon (letting nfsd stay at
564 * whatever uid it wants to). It normally shadows "euid", except when
565 * explicitly set by setfsuid() or for access..
566 */
567 asmlinkage long sys_setfsuid(uid_t uid)
568 {
569 int old_fsuid;
570
571 old_fsuid = current->fsuid;
572 if (uid == current->uid || uid == current->euid ||
573 uid == current->suid || uid == current->fsuid ||
574 capable(CAP_SETUID))
575 current->fsuid = uid;
576 if (current->fsuid != old_fsuid)
577 current->dumpable = 0;
578
579 /* We emulate fsuid by essentially doing a scaled-down version
580 * of what we did in setresuid and friends. However, we only
581 * operate on the fs-specific bits of the process' effective
582 * capabilities
583 *
584 * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
585 * if not, we might be a bit too harsh here.
586 */
587
588 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
589 if (old_fsuid == 0 && current->fsuid != 0) {
590 cap_t(current->cap_effective) &= ~CAP_FS_MASK;
591 }
592 if (old_fsuid != 0 && current->fsuid == 0) {
593 cap_t(current->cap_effective) |=
594 (cap_t(current->cap_permitted) & CAP_FS_MASK);
595 }
596 }
597
598 return old_fsuid;
599 }
600
601 /*
602 * Samma på svenska..
603 */
604 asmlinkage long sys_setfsgid(gid_t gid)
605 {
606 int old_fsgid;
607
608 old_fsgid = current->fsgid;
609 if (gid == current->gid || gid == current->egid ||
610 gid == current->sgid || gid == current->fsgid ||
611 capable(CAP_SETGID))
612 current->fsgid = gid;
613 if (current->fsgid != old_fsgid)
614 current->dumpable = 0;
615
616 return old_fsgid;
617 }
618
619 asmlinkage long sys_times(struct tms * tbuf)
620 {
621 /*
622 * In the SMP world we might just be unlucky and have one of
623 * the times increment as we use it. Since the value is an
624 * atomically safe type this is just fine. Conceptually its
625 * as if the syscall took an instant longer to occur.
626 */
627 if (tbuf)
628 if (copy_to_user(tbuf, ¤t->times, sizeof(struct tms)))
629 return -EFAULT;
630 return jiffies;
631 }
632
633 /*
634 * This needs some heavy checking ...
635 * I just haven't the stomach for it. I also don't fully
636 * understand sessions/pgrp etc. Let somebody who does explain it.
637 *
638 * OK, I think I have the protection semantics right.... this is really
639 * only important on a multi-user system anyway, to make sure one user
640 * can't send a signal to a process owned by another. -TYT, 12/12/91
641 *
642 * Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
643 * LBT 04.03.94
644 */
645
646 asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
647 {
648 struct task_struct * p;
649 int err = -EINVAL;
650
651 if (!pid)
652 pid = current->pid;
653 if (!pgid)
654 pgid = pid;
655 if (pgid < 0)
656 return -EINVAL;
657
658 /* From this point forward we keep holding onto the tasklist lock
659 * so that our parent does not change from under us. -DaveM
660 */
661 read_lock(&tasklist_lock);
662
663 err = -ESRCH;
664 p = find_task_by_pid(pid);
665 if (!p)
666 goto out;
667
668 if (p->p_pptr == current || p->p_opptr == current) {
669 err = -EPERM;
670 if (p->session != current->session)
671 goto out;
672 err = -EACCES;
673 if (p->did_exec)
674 goto out;
675 } else if (p != current)
676 goto out;
677 err = -EPERM;
678 if (p->leader)
679 goto out;
680 if (pgid != pid) {
681 struct task_struct * tmp;
682 for_each_task (tmp) {
683 if (tmp->pgrp == pgid &&
684 tmp->session == current->session)
685 goto ok_pgid;
686 }
687 goto out;
688 }
689
690 ok_pgid:
691 p->pgrp = pgid;
692 err = 0;
693 out:
694 /* All paths lead to here, thus we are safe. -DaveM */
695 read_unlock(&tasklist_lock);
696 return err;
697 }
698
699 asmlinkage long sys_getpgid(pid_t pid)
700 {
701 if (!pid) {
702 return current->pgrp;
703 } else {
704 int retval;
705 struct task_struct *p;
706
707 read_lock(&tasklist_lock);
708 p = find_task_by_pid(pid);
709
710 retval = -ESRCH;
711 if (p)
712 retval = p->pgrp;
713 read_unlock(&tasklist_lock);
714 return retval;
715 }
716 }
717
718 asmlinkage long sys_getpgrp(void)
719 {
720 /* SMP - assuming writes are word atomic this is fine */
721 return current->pgrp;
722 }
723
724 asmlinkage long sys_getsid(pid_t pid)
725 {
726 if (!pid) {
727 return current->session;
728 } else {
729 int retval;
730 struct task_struct *p;
731
732 read_lock(&tasklist_lock);
733 p = find_task_by_pid(pid);
734
735 retval = -ESRCH;
736 if(p)
737 retval = p->session;
738 read_unlock(&tasklist_lock);
739 return retval;
740 }
741 }
742
743 asmlinkage long sys_setsid(void)
744 {
745 struct task_struct * p;
746 int err = -EPERM;
747
748 read_lock(&tasklist_lock);
749 for_each_task(p) {
750 if (p->pgrp == current->pid)
751 goto out;
752 }
753
754 current->leader = 1;
755 current->session = current->pgrp = current->pid;
756 current->tty = NULL;
757 current->tty_old_pgrp = 0;
758 err = current->pgrp;
759 out:
760 read_unlock(&tasklist_lock);
761 return err;
762 }
763
764 /*
765 * Supplementary group IDs
766 */
767 asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist)
768 {
769 int i;
770
771 /*
772 * SMP: Nobody else can change our grouplist. Thus we are
773 * safe.
774 */
775
776 if (gidsetsize < 0)
777 return -EINVAL;
778 i = current->ngroups;
779 if (gidsetsize) {
780 if (i > gidsetsize)
781 return -EINVAL;
782 if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i))
783 return -EFAULT;
784 }
785 return i;
786 }
787
788 /*
789 * SMP: Our groups are not shared. We can copy to/from them safely
790 * without another task interfering.
791 */
792
793 asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist)
794 {
795 if (!capable(CAP_SETGID))
796 return -EPERM;
797 if ((unsigned) gidsetsize > NGROUPS)
798 return -EINVAL;
799 if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
800 return -EFAULT;
801 current->ngroups = gidsetsize;
802 return 0;
803 }
804
805 int in_group_p(gid_t grp)
806 {
807 if (grp != current->fsgid) {
808 int i = current->ngroups;
809 if (i) {
810 gid_t *groups = current->groups;
811 do {
812 if (*groups == grp)
813 goto out;
814 groups++;
815 i--;
816 } while (i);
817 }
818 return 0;
819 }
820 out:
821 return 1;
822 }
823
824 /* Like in_group_p, but testing against egid, not fsgid */
825 int in_egroup_p(gid_t grp)
826 {
827 if (grp != current->egid) {
828 int i = current->ngroups;
829 if (i) {
830 gid_t *groups = current->groups;
831 do {
832 if (*groups == grp)
833 goto out;
834 groups++;
835 i--;
836 } while (i);
837 }
838 return 0;
839 }
840 out:
841 return 1;
842 }
843
844 DECLARE_RWSEM(uts_sem);
845
846 asmlinkage long sys_newuname(struct new_utsname * name)
847 {
848 int errno = 0;
849
850 down_read(&uts_sem);
851 if (copy_to_user(name,&system_utsname,sizeof *name))
852 errno = -EFAULT;
853 up_read(&uts_sem);
854 return errno;
855 }
856
857 asmlinkage long sys_sethostname(char *name, int len)
858 {
859 int errno;
860
861 if (!capable(CAP_SYS_ADMIN))
862 return -EPERM;
863 if (len < 0 || len > __NEW_UTS_LEN)
864 return -EINVAL;
865 down_write(&uts_sem);
866 errno = -EFAULT;
867 if (!copy_from_user(system_utsname.nodename, name, len)) {
868 system_utsname.nodename[len] = 0;
869 errno = 0;
870 }
871 up_write(&uts_sem);
872 return errno;
873 }
874
875 asmlinkage long sys_gethostname(char *name, int len)
876 {
877 int i, errno;
878
879 if (len < 0)
880 return -EINVAL;
881 down_read(&uts_sem);
882 i = 1 + strlen(system_utsname.nodename);
883 if (i > len)
884 i = len;
885 errno = 0;
886 if (copy_to_user(name, system_utsname.nodename, i))
887 errno = -EFAULT;
888 up_read(&uts_sem);
889 return errno;
890 }
891
892 /*
893 * Only setdomainname; getdomainname can be implemented by calling
894 * uname()
895 */
896 asmlinkage long sys_setdomainname(char *name, int len)
897 {
898 int errno;
899
900 if (!capable(CAP_SYS_ADMIN))
901 return -EPERM;
902 if (len < 0 || len > __NEW_UTS_LEN)
903 return -EINVAL;
904
905 down_write(&uts_sem);
906 errno = -EFAULT;
907 if (!copy_from_user(system_utsname.domainname, name, len)) {
908 errno = 0;
909 system_utsname.domainname[len] = 0;
910 }
911 up_write(&uts_sem);
912 return errno;
913 }
914
915 asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim)
916 {
917 if (resource >= RLIM_NLIMITS)
918 return -EINVAL;
919 else
920 return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
921 ? -EFAULT : 0;
922 }
923
924 #if !defined(__ia64__)
925
926 /*
927 * Back compatibility for getrlimit. Needed for some apps.
928 */
929
930 asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim)
931 {
932 struct rlimit x;
933 if (resource >= RLIM_NLIMITS)
934 return -EINVAL;
935
936 memcpy(&x, current->rlim + resource, sizeof(*rlim));
937 if(x.rlim_cur > 0x7FFFFFFF)
938 x.rlim_cur = 0x7FFFFFFF;
939 if(x.rlim_max > 0x7FFFFFFF)
940 x.rlim_max = 0x7FFFFFFF;
941 return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0;
942 }
943
944 #endif
945
946 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
947 {
948 struct rlimit new_rlim, *old_rlim;
949
950 if (resource >= RLIM_NLIMITS)
951 return -EINVAL;
952 if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
953 return -EFAULT;
954 if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0)
955 return -EINVAL;
956 old_rlim = current->rlim + resource;
957 if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
958 (new_rlim.rlim_max > old_rlim->rlim_max)) &&
959 !capable(CAP_SYS_RESOURCE))
960 return -EPERM;
961 if (resource == RLIMIT_NOFILE) {
962 if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
963 return -EPERM;
964 }
965 *old_rlim = new_rlim;
966 return 0;
967 }
968
969 /*
970 * It would make sense to put struct rusage in the task_struct,
971 * except that would make the task_struct be *really big*. After
972 * task_struct gets moved into malloc'ed memory, it would
973 * make sense to do this. It will make moving the rest of the information
974 * a lot simpler! (Which we're not doing right now because we're not
975 * measuring them yet).
976 *
977 * This is SMP safe. Either we are called from sys_getrusage on ourselves
978 * below (we know we aren't going to exit/disappear and only we change our
979 * rusage counters), or we are called from wait4() on a process which is
980 * either stopped or zombied. In the zombied case the task won't get
981 * reaped till shortly after the call to getrusage(), in both cases the
982 * task being examined is in a frozen state so the counters won't change.
983 *
984 * FIXME! Get the fault counts properly!
985 */
986 int getrusage(struct task_struct *p, int who, struct rusage *ru)
987 {
988 struct rusage r;
989
990 memset((char *) &r, 0, sizeof(r));
991 switch (who) {
992 case RUSAGE_SELF:
993 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime);
994 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime);
995 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime);
996 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime);
997 r.ru_minflt = p->min_flt;
998 r.ru_majflt = p->maj_flt;
999 r.ru_nswap = p->nswap;
1000 break;
1001 case RUSAGE_CHILDREN:
1002 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_cutime);
1003 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_cutime);
1004 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_cstime);
1005 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_cstime);
1006 r.ru_minflt = p->cmin_flt;
1007 r.ru_majflt = p->cmaj_flt;
1008 r.ru_nswap = p->cnswap;
1009 break;
1010 default:
1011 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime + p->times.tms_cutime);
1012 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime + p->times.tms_cutime);
1013 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime + p->times.tms_cstime);
1014 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime + p->times.tms_cstime);
1015 r.ru_minflt = p->min_flt + p->cmin_flt;
1016 r.ru_majflt = p->maj_flt + p->cmaj_flt;
1017 r.ru_nswap = p->nswap + p->cnswap;
1018 break;
1019 }
1020 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
1021 }
1022
1023 asmlinkage long sys_getrusage(int who, struct rusage *ru)
1024 {
1025 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
1026 return -EINVAL;
1027 return getrusage(current, who, ru);
1028 }
1029
1030 asmlinkage long sys_umask(int mask)
1031 {
1032 mask = xchg(¤t->fs->umask, mask & S_IRWXUGO);
1033 return mask;
1034 }
1035
1036 asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1037 unsigned long arg4, unsigned long arg5)
1038 {
1039 int error = 0;
1040 int sig;
1041
1042 switch (option) {
1043 case PR_SET_PDEATHSIG:
1044 sig = arg2;
1045 if (sig > _NSIG) {
1046 error = -EINVAL;
1047 break;
1048 }
1049 current->pdeath_signal = sig;
1050 break;
1051 case PR_GET_PDEATHSIG:
1052 error = put_user(current->pdeath_signal, (int *)arg2);
1053 break;
1054 case PR_GET_DUMPABLE:
1055 if (current->dumpable)
1056 error = 1;
1057 break;
1058 case PR_SET_DUMPABLE:
1059 if (arg2 != 0 && arg2 != 1) {
1060 error = -EINVAL;
1061 break;
1062 }
1063 current->dumpable = arg2;
1064 break;
1065 default:
1066 error = -EINVAL;
1067 break;
1068 }
1069 return error;
1070 }
1071
1072
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.