1
2
3
4
5
6
7#include <linux/module.h>
8#include <linux/mm.h>
9#include <linux/utsname.h>
10#include <linux/mman.h>
11#include <linux/smp_lock.h>
12#include <linux/notifier.h>
13#include <linux/reboot.h>
14#include <linux/prctl.h>
15#include <linux/init.h>
16#include <linux/highuid.h>
17
18#include <asm/uaccess.h>
19#include <asm/io.h>
20
21#ifndef SET_UNALIGN_CTL
22# define SET_UNALIGN_CTL(a,b) (-EINVAL)
23#endif
24#ifndef GET_UNALIGN_CTL
25# define GET_UNALIGN_CTL(a,b) (-EINVAL)
26#endif
27#ifndef SET_FPEMU_CTL
28# define SET_FPEMU_CTL(a,b) (-EINVAL)
29#endif
30#ifndef GET_FPEMU_CTL
31# define GET_FPEMU_CTL(a,b) (-EINVAL)
32#endif
33#ifndef SET_FPEXC_CTL
34# define SET_FPEXC_CTL(a,b) (-EINVAL)
35#endif
36#ifndef GET_FPEXC_CTL
37# define GET_FPEXC_CTL(a,b) (-EINVAL)
38#endif
39
40
41
42
43
44
45int overflowuid = DEFAULT_OVERFLOWUID;
46int overflowgid = DEFAULT_OVERFLOWGID;
47
48
49
50
51
52
53int fs_overflowuid = DEFAULT_FS_OVERFLOWUID;
54int fs_overflowgid = DEFAULT_FS_OVERFLOWUID;
55
56
57
58
59
60int C_A_D = 1;
61int cad_pid = 1;
62
63
64
65
66
67
68
69
70static struct notifier_block *reboot_notifier_list;
71rwlock_t notifier_lock = RW_LOCK_UNLOCKED;
72
73
74
75
76
77
78
79
80
81
82
83int notifier_chain_register(struct notifier_block **list, struct notifier_block *n)
84{
85 write_lock(¬ifier_lock);
86 while(*list)
87 {
88 if(n->priority > (*list)->priority)
89 break;
90 list= &((*list)->next);
91 }
92 n->next = *list;
93 *list=n;
94 write_unlock(¬ifier_lock);
95 return 0;
96}
97
98
99
100
101
102
103
104
105
106
107
108int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n)
109{
110 write_lock(¬ifier_lock);
111 while((*nl)!=NULL)
112 {
113 if((*nl)==n)
114 {
115 *nl=n->next;
116 write_unlock(¬ifier_lock);
117 return 0;
118 }
119 nl=&((*nl)->next);
120 }
121 write_unlock(¬ifier_lock);
122 return -ENOENT;
123}
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
142{
143 int ret=NOTIFY_DONE;
144 struct notifier_block *nb = *n;
145
146 while(nb)
147 {
148 ret=nb->notifier_call(nb,val,v);
149 if(ret&NOTIFY_STOP_MASK)
150 {
151 return ret;
152 }
153 nb=nb->next;
154 }
155 return ret;
156}
157
158
159
160
161
162
163
164
165
166
167
168
169int register_reboot_notifier(struct notifier_block * nb)
170{
171 return notifier_chain_register(&reboot_notifier_list, nb);
172}
173
174
175
176
177
178
179
180
181
182
183
184int unregister_reboot_notifier(struct notifier_block * nb)
185{
186 return notifier_chain_unregister(&reboot_notifier_list, nb);
187}
188
189asmlinkage long sys_ni_syscall(void)
190{
191 return -ENOSYS;
192}
193
194static int proc_sel(struct task_struct *p, int which, int who)
195{
196 if(p->pid)
197 {
198 switch (which) {
199 case PRIO_PROCESS:
200 if (!who && p == current)
201 return 1;
202 return(p->pid == who);
203 case PRIO_PGRP:
204 if (!who)
205 who = current->pgrp;
206 return(p->pgrp == who);
207 case PRIO_USER:
208 if (!who)
209 who = current->uid;
210 return(p->uid == who);
211 }
212 }
213 return 0;
214}
215
216asmlinkage long sys_setpriority(int which, int who, int niceval)
217{
218 struct task_struct *p;
219 int error;
220
221 if (which > 2 || which < 0)
222 return -EINVAL;
223
224
225 error = -ESRCH;
226 if (niceval < -20)
227 niceval = -20;
228 if (niceval > 19)
229 niceval = 19;
230
231 read_lock(&tasklist_lock);
232 for_each_task(p) {
233 if (!proc_sel(p, which, who))
234 continue;
235 if (p->uid != current->euid &&
236 p->uid != current->uid && !capable(CAP_SYS_NICE)) {
237 error = -EPERM;
238 continue;
239 }
240 if (error == -ESRCH)
241 error = 0;
242 if (niceval < p->nice && !capable(CAP_SYS_NICE))
243 error = -EACCES;
244 else
245 p->nice = niceval;
246 }
247 read_unlock(&tasklist_lock);
248
249 return error;
250}
251
252
253
254
255
256
257
258asmlinkage long sys_getpriority(int which, int who)
259{
260 struct task_struct *p;
261 long retval = -ESRCH;
262
263 if (which > 2 || which < 0)
264 return -EINVAL;
265
266 read_lock(&tasklist_lock);
267 for_each_task (p) {
268 long niceval;
269 if (!proc_sel(p, which, who))
270 continue;
271 niceval = 20 - p->nice;
272 if (niceval > retval)
273 retval = niceval;
274 }
275 read_unlock(&tasklist_lock);
276
277 return retval;
278}
279
280
281
282
283
284
285
286
287
288
289asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void * arg)
290{
291 char buffer[256];
292
293
294 if (!capable(CAP_SYS_BOOT))
295 return -EPERM;
296
297
298 if (magic1 != LINUX_REBOOT_MAGIC1 ||
299 (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A &&
300 magic2 != LINUX_REBOOT_MAGIC2B))
301 return -EINVAL;
302
303 lock_kernel();
304 switch (cmd) {
305 case LINUX_REBOOT_CMD_RESTART:
306 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
307 printk(KERN_EMERG "Restarting system.\n");
308 machine_restart(NULL);
309 break;
310
311 case LINUX_REBOOT_CMD_CAD_ON:
312 C_A_D = 1;
313 break;
314
315 case LINUX_REBOOT_CMD_CAD_OFF:
316 C_A_D = 0;
317 break;
318
319 case LINUX_REBOOT_CMD_HALT:
320 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
321 printk(KERN_EMERG "System halted.\n");
322 machine_halt();
323 do_exit(0);
324 break;
325
326 case LINUX_REBOOT_CMD_POWER_OFF:
327 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
328 printk(KERN_EMERG "Power down.\n");
329 machine_power_off();
330 do_exit(0);
331 break;
332
333 case LINUX_REBOOT_CMD_RESTART2:
334 if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) {
335 unlock_kernel();
336 return -EFAULT;
337 }
338 buffer[sizeof(buffer) - 1] = '\0';
339
340 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
341 printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
342 machine_restart(buffer);
343 break;
344
345 default:
346 unlock_kernel();
347 return -EINVAL;
348 }
349 unlock_kernel();
350 return 0;
351}
352
353static void deferred_cad(void *dummy)
354{
355 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
356 machine_restart(NULL);
357}
358
359
360
361
362
363
364void ctrl_alt_del(void)
365{
366 static struct tq_struct cad_tq = {
367 routine: deferred_cad,
368 };
369
370 if (C_A_D)
371 schedule_task(&cad_tq);
372 else
373 kill_proc(cad_pid, SIGINT, 1);
374}
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
396{
397 int old_rgid = current->gid;
398 int old_egid = current->egid;
399 int new_rgid = old_rgid;
400 int new_egid = old_egid;
401
402 if (rgid != (gid_t) -1) {
403 if ((old_rgid == rgid) ||
404 (current->egid==rgid) ||
405 capable(CAP_SETGID))
406 new_rgid = rgid;
407 else
408 return -EPERM;
409 }
410 if (egid != (gid_t) -1) {
411 if ((old_rgid == egid) ||
412 (current->egid == egid) ||
413 (current->sgid == egid) ||
414 capable(CAP_SETGID))
415 new_egid = egid;
416 else {
417 return -EPERM;
418 }
419 }
420 if (new_egid != old_egid)
421 {
422 current->mm->dumpable = 0;
423 wmb();
424 }
425 if (rgid != (gid_t) -1 ||
426 (egid != (gid_t) -1 && egid != old_rgid))
427 current->sgid = new_egid;
428 current->fsgid = new_egid;
429 current->egid = new_egid;
430 current->gid = new_rgid;
431 return 0;
432}
433
434
435
436
437
438
439asmlinkage long sys_setgid(gid_t gid)
440{
441 int old_egid = current->egid;
442
443 if (capable(CAP_SETGID))
444 {
445 if(old_egid != gid)
446 {
447 current->mm->dumpable=0;
448 wmb();
449 }
450 current->gid = current->egid = current->sgid = current->fsgid = gid;
451 }
452 else if ((gid == current->gid) || (gid == current->sgid))
453 {
454 if(old_egid != gid)
455 {
456 current->mm->dumpable=0;
457 wmb();
458 }
459 current->egid = current->fsgid = gid;
460 }
461 else
462 return -EPERM;
463 return 0;
464}
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495static inline void cap_emulate_setxuid(int old_ruid, int old_euid,
496 int old_suid)
497{
498 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
499 (current->uid != 0 && current->euid != 0 && current->suid != 0) &&
500 !current->keep_capabilities) {
501 cap_clear(current->cap_permitted);
502 cap_clear(current->cap_effective);
503 }
504 if (old_euid == 0 && current->euid != 0) {
505 cap_clear(current->cap_effective);
506 }
507 if (old_euid != 0 && current->euid == 0) {
508 current->cap_effective = current->cap_permitted;
509 }
510}
511
512static int set_user(uid_t new_ruid, int dumpclear)
513{
514 struct user_struct *new_user;
515
516 new_user = alloc_uid(new_ruid);
517 if (!new_user)
518 return -EAGAIN;
519 switch_uid(new_user);
520
521 if(dumpclear)
522 {
523 current->mm->dumpable = 0;
524 wmb();
525 }
526 current->uid = new_ruid;
527 return 0;
528}
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
546{
547 int old_ruid, old_euid, old_suid, new_ruid, new_euid;
548
549 new_ruid = old_ruid = current->uid;
550 new_euid = old_euid = current->euid;
551 old_suid = current->suid;
552
553 if (ruid != (uid_t) -1) {
554 new_ruid = ruid;
555 if ((old_ruid != ruid) &&
556 (current->euid != ruid) &&
557 !capable(CAP_SETUID))
558 return -EPERM;
559 }
560
561 if (euid != (uid_t) -1) {
562 new_euid = euid;
563 if ((old_ruid != euid) &&
564 (current->euid != euid) &&
565 (current->suid != euid) &&
566 !capable(CAP_SETUID))
567 return -EPERM;
568 }
569
570 if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)
571 return -EAGAIN;
572
573 if (new_euid != old_euid)
574 {
575 current->mm->dumpable=0;
576 wmb();
577 }
578 current->fsuid = current->euid = new_euid;
579 if (ruid != (uid_t) -1 ||
580 (euid != (uid_t) -1 && euid != old_ruid))
581 current->suid = current->euid;
582 current->fsuid = current->euid;
583
584 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
585 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
586 }
587
588 return 0;
589}
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604asmlinkage long sys_setuid(uid_t uid)
605{
606 int old_euid = current->euid;
607 int old_ruid, old_suid, new_ruid, new_suid;
608
609 old_ruid = new_ruid = current->uid;
610 old_suid = current->suid;
611 new_suid = old_suid;
612
613 if (capable(CAP_SETUID)) {
614 if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
615 return -EAGAIN;
616 new_suid = uid;
617 } else if ((uid != current->uid) && (uid != new_suid))
618 return -EPERM;
619
620 if (old_euid != uid)
621 {
622 current->mm->dumpable = 0;
623 wmb();
624 }
625 current->fsuid = current->euid = uid;
626 current->suid = new_suid;
627
628 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
629 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
630 }
631
632 return 0;
633}
634
635
636
637
638
639
640asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
641{
642 int old_ruid = current->uid;
643 int old_euid = current->euid;
644 int old_suid = current->suid;
645
646 if (!capable(CAP_SETUID)) {
647 if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
648 (ruid != current->euid) && (ruid != current->suid))
649 return -EPERM;
650 if ((euid != (uid_t) -1) && (euid != current->uid) &&
651 (euid != current->euid) && (euid != current->suid))
652 return -EPERM;
653 if ((suid != (uid_t) -1) && (suid != current->uid) &&
654 (suid != current->euid) && (suid != current->suid))
655 return -EPERM;
656 }
657 if (ruid != (uid_t) -1) {
658 if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)
659 return -EAGAIN;
660 }
661 if (euid != (uid_t) -1) {
662 if (euid != current->euid)
663 {
664 current->mm->dumpable = 0;
665 wmb();
666 }
667 current->euid = euid;
668 }
669 current->fsuid = current->euid;
670 if (suid != (uid_t) -1)
671 current->suid = suid;
672
673 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
674 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
675 }
676
677 return 0;
678}
679
680asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
681{
682 int retval;
683
684 if (!(retval = put_user(current->uid, ruid)) &&
685 !(retval = put_user(current->euid, euid)))
686 retval = put_user(current->suid, suid);
687
688 return retval;
689}
690
691
692
693
694asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
695{
696 if (!capable(CAP_SETGID)) {
697 if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
698 (rgid != current->egid) && (rgid != current->sgid))
699 return -EPERM;
700 if ((egid != (gid_t) -1) && (egid != current->gid) &&
701 (egid != current->egid) && (egid != current->sgid))
702 return -EPERM;
703 if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
704 (sgid != current->egid) && (sgid != current->sgid))
705 return -EPERM;
706 }
707 if (egid != (gid_t) -1) {
708 if (egid != current->egid)
709 {
710 current->mm->dumpable = 0;
711 wmb();
712 }
713 current->egid = egid;
714 }
715 current->fsgid = current->egid;
716 if (rgid != (gid_t) -1)
717 current->gid = rgid;
718 if (sgid != (gid_t) -1)
719 current->sgid = sgid;
720 return 0;
721}
722
723asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
724{
725 int retval;
726
727 if (!(retval = put_user(current->gid, rgid)) &&
728 !(retval = put_user(current->egid, egid)))
729 retval = put_user(current->sgid, sgid);
730
731 return retval;
732}
733
734
735
736
737
738
739
740
741asmlinkage long sys_setfsuid(uid_t uid)
742{
743 int old_fsuid;
744
745 old_fsuid = current->fsuid;
746 if (uid == current->uid || uid == current->euid ||
747 uid == current->suid || uid == current->fsuid ||
748 capable(CAP_SETUID))
749 {
750 if (uid != old_fsuid)
751 {
752 current->mm->dumpable = 0;
753 wmb();
754 }
755 current->fsuid = uid;
756 }
757
758
759
760
761
762
763
764
765
766
767 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
768 if (old_fsuid == 0 && current->fsuid != 0) {
769 cap_t(current->cap_effective) &= ~CAP_FS_MASK;
770 }
771 if (old_fsuid != 0 && current->fsuid == 0) {
772 cap_t(current->cap_effective) |=
773 (cap_t(current->cap_permitted) & CAP_FS_MASK);
774 }
775 }
776
777 return old_fsuid;
778}
779
780
781
782
783asmlinkage long sys_setfsgid(gid_t gid)
784{
785 int old_fsgid;
786
787 old_fsgid = current->fsgid;
788 if (gid == current->gid || gid == current->egid ||
789 gid == current->sgid || gid == current->fsgid ||
790 capable(CAP_SETGID))
791 {
792 if (gid != old_fsgid)
793 {
794 current->mm->dumpable = 0;
795 wmb();
796 }
797 current->fsgid = gid;
798 }
799 return old_fsgid;
800}
801
802asmlinkage long sys_times(struct tms * tbuf)
803{
804
805
806
807
808
809
810 if (tbuf)
811 if (copy_to_user(tbuf, ¤t->times, sizeof(struct tms)))
812 return -EFAULT;
813 return jiffies;
814}
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
830{
831 struct task_struct * p;
832 int err = -EINVAL;
833
834 if (!pid)
835 pid = current->pid;
836 if (!pgid)
837 pgid = pid;
838 if (pgid < 0)
839 return -EINVAL;
840
841
842
843
844 read_lock(&tasklist_lock);
845
846 err = -ESRCH;
847 p = find_task_by_pid(pid);
848 if (!p)
849 goto out;
850
851 if (p->p_pptr == current || p->p_opptr == current) {
852 err = -EPERM;
853 if (p->session != current->session)
854 goto out;
855 err = -EACCES;
856 if (p->did_exec)
857 goto out;
858 } else if (p != current)
859 goto out;
860 err = -EPERM;
861 if (p->leader)
862 goto out;
863 if (pgid != pid) {
864 struct task_struct * tmp;
865 for_each_task (tmp) {
866 if (tmp->pgrp == pgid &&
867 tmp->session == current->session)
868 goto ok_pgid;
869 }
870 goto out;
871 }
872
873ok_pgid:
874 p->pgrp = pgid;
875 err = 0;
876out:
877
878 read_unlock(&tasklist_lock);
879 return err;
880}
881
882asmlinkage long sys_getpgid(pid_t pid)
883{
884 if (!pid) {
885 return current->pgrp;
886 } else {
887 int retval;
888 struct task_struct *p;
889
890 read_lock(&tasklist_lock);
891 p = find_task_by_pid(pid);
892
893 retval = -ESRCH;
894 if (p)
895 retval = p->pgrp;
896 read_unlock(&tasklist_lock);
897 return retval;
898 }
899}
900
901asmlinkage long sys_getpgrp(void)
902{
903
904 return current->pgrp;
905}
906
907asmlinkage long sys_getsid(pid_t pid)
908{
909 if (!pid) {
910 return current->session;
911 } else {
912 int retval;
913 struct task_struct *p;
914
915 read_lock(&tasklist_lock);
916 p = find_task_by_pid(pid);
917
918 retval = -ESRCH;
919 if(p)
920 retval = p->session;
921 read_unlock(&tasklist_lock);
922 return retval;
923 }
924}
925
926asmlinkage long sys_setsid(void)
927{
928 struct task_struct * p;
929 int err = -EPERM;
930
931 read_lock(&tasklist_lock);
932 for_each_task(p) {
933 if (p->pgrp == current->pid)
934 goto out;
935 }
936
937 current->leader = 1;
938 current->session = current->pgrp = current->pid;
939 current->tty = NULL;
940 current->tty_old_pgrp = 0;
941 err = current->pgrp;
942out:
943 read_unlock(&tasklist_lock);
944 return err;
945}
946
947
948
949
950asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist)
951{
952 int i;
953
954
955
956
957
958
959 if (gidsetsize < 0)
960 return -EINVAL;
961 i = current->ngroups;
962 if (gidsetsize) {
963 if (i > gidsetsize)
964 return -EINVAL;
965 if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i))
966 return -EFAULT;
967 }
968 return i;
969}
970
971
972
973
974
975
976asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist)
977{
978 if (!capable(CAP_SETGID))
979 return -EPERM;
980 if ((unsigned) gidsetsize > NGROUPS)
981 return -EINVAL;
982 if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
983 return -EFAULT;
984 current->ngroups = gidsetsize;
985 return 0;
986}
987
988static int supplemental_group_member(gid_t grp)
989{
990 int i = current->ngroups;
991
992 if (i) {
993 gid_t *groups = current->groups;
994 do {
995 if (*groups == grp)
996 return 1;
997 groups++;
998 i--;
999 } while (i);
1000 }
1001 return 0;
1002}
1003
1004
1005
1006
1007int in_group_p(gid_t grp)
1008{
1009 int retval = 1;
1010 if (grp != current->fsgid)
1011 retval = supplemental_group_member(grp);
1012 return retval;
1013}
1014
1015int in_egroup_p(gid_t grp)
1016{
1017 int retval = 1;
1018 if (grp != current->egid)
1019 retval = supplemental_group_member(grp);
1020 return retval;
1021}
1022
1023DECLARE_RWSEM(uts_sem);
1024
1025asmlinkage long sys_newuname(struct new_utsname * name)
1026{
1027 int errno = 0;
1028
1029 down_read(&uts_sem);
1030 if (copy_to_user(name,&system_utsname,sizeof *name))
1031 errno = -EFAULT;
1032 up_read(&uts_sem);
1033 return errno;
1034}
1035
1036asmlinkage long sys_sethostname(char *name, int len)
1037{
1038 int errno;
1039 char tmp[__NEW_UTS_LEN];
1040
1041 if (!capable(CAP_SYS_ADMIN))
1042 return -EPERM;
1043 if (len < 0 || len > __NEW_UTS_LEN)
1044 return -EINVAL;
1045 down_write(&uts_sem);
1046 errno = -EFAULT;
1047 if (!copy_from_user(tmp, name, len)) {
1048 memcpy(system_utsname.nodename, tmp, len);
1049 system_utsname.nodename[len] = 0;
1050 errno = 0;
1051 }
1052 up_write(&uts_sem);
1053 return errno;
1054}
1055
1056asmlinkage long sys_gethostname(char *name, int len)
1057{
1058 int i, errno;
1059
1060 if (len < 0)
1061 return -EINVAL;
1062 down_read(&uts_sem);
1063 i = 1 + strlen(system_utsname.nodename);
1064 if (i > len)
1065 i = len;
1066 errno = 0;
1067 if (copy_to_user(name, system_utsname.nodename, i))
1068 errno = -EFAULT;
1069 up_read(&uts_sem);
1070 return errno;
1071}
1072
1073
1074
1075
1076
1077asmlinkage long sys_setdomainname(char *name, int len)
1078{
1079 int errno;
1080 char tmp[__NEW_UTS_LEN];
1081
1082 if (!capable(CAP_SYS_ADMIN))
1083 return -EPERM;
1084 if (len < 0 || len > __NEW_UTS_LEN)
1085 return -EINVAL;
1086
1087 down_write(&uts_sem);
1088 errno = -EFAULT;
1089 if (!copy_from_user(tmp, name, len)) {
1090 memcpy(system_utsname.domainname, tmp, len);
1091 system_utsname.domainname[len] = 0;
1092 errno = 0;
1093 }
1094 up_write(&uts_sem);
1095 return errno;
1096}
1097
1098asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim)
1099{
1100 if (resource >= RLIM_NLIMITS)
1101 return -EINVAL;
1102 else
1103 return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
1104 ? -EFAULT : 0;
1105}
1106
1107#if !defined(__ia64__)
1108
1109
1110
1111
1112
1113asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim)
1114{
1115 struct rlimit x;
1116 if (resource >= RLIM_NLIMITS)
1117 return -EINVAL;
1118
1119 memcpy(&x, current->rlim + resource, sizeof(*rlim));
1120 if(x.rlim_cur > 0x7FFFFFFF)
1121 x.rlim_cur = 0x7FFFFFFF;
1122 if(x.rlim_max > 0x7FFFFFFF)
1123 x.rlim_max = 0x7FFFFFFF;
1124 return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0;
1125}
1126
1127#endif
1128
1129asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
1130{
1131 struct rlimit new_rlim, *old_rlim;
1132
1133 if (resource >= RLIM_NLIMITS)
1134 return -EINVAL;
1135 if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
1136 return -EFAULT;
1137 if (new_rlim.rlim_cur > new_rlim.rlim_max)
1138 return -EINVAL;
1139 old_rlim = current->rlim + resource;
1140 if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
1141 (new_rlim.rlim_max > old_rlim->rlim_max)) &&
1142 !capable(CAP_SYS_RESOURCE))
1143 return -EPERM;
1144 if (resource == RLIMIT_NOFILE) {
1145 if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
1146 return -EPERM;
1147 }
1148 *old_rlim = new_rlim;
1149 return 0;
1150}
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169int getrusage(struct task_struct *p, int who, struct rusage *ru)
1170{
1171 struct rusage r;
1172
1173 memset((char *) &r, 0, sizeof(r));
1174 switch (who) {
1175 case RUSAGE_SELF:
1176 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime);
1177 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime);
1178 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime);
1179 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime);
1180 r.ru_minflt = p->min_flt;
1181 r.ru_majflt = p->maj_flt;
1182 r.ru_nswap = p->nswap;
1183 break;
1184 case RUSAGE_CHILDREN:
1185 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_cutime);
1186 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_cutime);
1187 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_cstime);
1188 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_cstime);
1189 r.ru_minflt = p->cmin_flt;
1190 r.ru_majflt = p->cmaj_flt;
1191 r.ru_nswap = p->cnswap;
1192 break;
1193 default:
1194 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime + p->times.tms_cutime);
1195 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime + p->times.tms_cutime);
1196 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime + p->times.tms_cstime);
1197 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime + p->times.tms_cstime);
1198 r.ru_minflt = p->min_flt + p->cmin_flt;
1199 r.ru_majflt = p->maj_flt + p->cmaj_flt;
1200 r.ru_nswap = p->nswap + p->cnswap;
1201 break;
1202 }
1203 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
1204}
1205
1206asmlinkage long sys_getrusage(int who, struct rusage *ru)
1207{
1208 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
1209 return -EINVAL;
1210 return getrusage(current, who, ru);
1211}
1212
1213asmlinkage long sys_umask(int mask)
1214{
1215 mask = xchg(¤t->fs->umask, mask & S_IRWXUGO);
1216 return mask;
1217}
1218
1219asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1220 unsigned long arg4, unsigned long arg5)
1221{
1222 int error = 0;
1223 int sig;
1224
1225 switch (option) {
1226 case PR_SET_PDEATHSIG:
1227 sig = arg2;
1228 if (sig < 0 || sig > _NSIG) {
1229 error = -EINVAL;
1230 break;
1231 }
1232 current->pdeath_signal = sig;
1233 break;
1234 case PR_GET_PDEATHSIG:
1235 error = put_user(current->pdeath_signal, (int *)arg2);
1236 break;
1237 case PR_GET_DUMPABLE:
1238 if (is_dumpable(current))
1239 error = 1;
1240 break;
1241 case PR_SET_DUMPABLE:
1242 if (arg2 != 0 && arg2 != 1) {
1243 error = -EINVAL;
1244 break;
1245 }
1246 current->mm->dumpable = arg2;
1247 break;
1248
1249 case PR_SET_UNALIGN:
1250 error = SET_UNALIGN_CTL(current, arg2);
1251 break;
1252 case PR_GET_UNALIGN:
1253 error = GET_UNALIGN_CTL(current, arg2);
1254 break;
1255 case PR_SET_FPEMU:
1256 error = SET_FPEMU_CTL(current, arg2);
1257 break;
1258 case PR_GET_FPEMU:
1259 error = GET_FPEMU_CTL(current, arg2);
1260 break;
1261 case PR_SET_FPEXC:
1262 error = SET_FPEXC_CTL(current, arg2);
1263 break;
1264 case PR_GET_FPEXC:
1265 error = GET_FPEXC_CTL(current, arg2);
1266 break;
1267
1268 case PR_GET_KEEPCAPS:
1269 if (current->keep_capabilities)
1270 error = 1;
1271 break;
1272 case PR_SET_KEEPCAPS:
1273 if (arg2 != 0 && arg2 != 1) {
1274 error = -EINVAL;
1275 break;
1276 }
1277 current->keep_capabilities = arg2;
1278 break;
1279 default:
1280 error = -EINVAL;
1281 break;
1282 }
1283 return error;
1284}
1285
1286EXPORT_SYMBOL(notifier_chain_register);
1287EXPORT_SYMBOL(notifier_chain_unregister);
1288EXPORT_SYMBOL(notifier_call_chain);
1289EXPORT_SYMBOL(register_reboot_notifier);
1290EXPORT_SYMBOL(unregister_reboot_notifier);
1291EXPORT_SYMBOL(in_group_p);
1292EXPORT_SYMBOL(in_egroup_p);
1293