This source file includes following definitions.
- sys_ni_syscall
- proc_sel
- sys_setpriority
- sys_getpriority
- sys_profil
- sys_ftime
- sys_break
- sys_stty
- sys_gtty
- sys_prof
- sys_reboot
- ctrl_alt_del
- sys_setregid
- sys_setgid
- sys_acct
- sys_phys
- sys_lock
- sys_mpx
- sys_ulimit
- sys_old_syscall
- sys_setreuid
- sys_setuid
- sys_setfsuid
- sys_setfsgid
- sys_times
- sys_brk
- sys_setpgid
- sys_getpgid
- sys_getpgrp
- sys_getsid
- sys_setsid
- sys_getgroups
- sys_setgroups
- in_group_p
- sys_newuname
- sys_uname
- sys_olduname
- sys_sethostname
- sys_gethostname
- sys_setdomainname
- sys_getrlimit
- sys_setrlimit
- getrusage
- sys_getrusage
- sys_umask
1
2
3
4
5
6
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/pagemap.h>
21 #include <linux/swap.h>
22
23 #include <asm/segment.h>
24 #include <asm/io.h>
25
26
27
28
29 static int C_A_D = 1;
30
31 extern void adjust_clock(void);
32
33 asmlinkage int sys_ni_syscall(void)
34 {
35 return -ENOSYS;
36 }
37
38 static int proc_sel(struct task_struct *p, int which, int who)
39 {
40 switch (which) {
41 case PRIO_PROCESS:
42 if (!who && p == current)
43 return 1;
44 return(p->pid == who);
45 case PRIO_PGRP:
46 if (!who)
47 who = current->pgrp;
48 return(p->pgrp == who);
49 case PRIO_USER:
50 if (!who)
51 who = current->uid;
52 return(p->uid == who);
53 }
54 return 0;
55 }
56
57 asmlinkage int sys_setpriority(int which, int who, int niceval)
58 {
59 struct task_struct *p;
60 int error = ESRCH;
61 unsigned int priority;
62
63 if (which > 2 || which < 0)
64 return -EINVAL;
65
66
67 priority = niceval;
68 if (niceval < 0)
69 priority = -niceval;
70 if (priority > 20)
71 priority = 20;
72 priority = (priority * DEF_PRIORITY + 10) / 20 + DEF_PRIORITY;
73
74 if (niceval >= 0) {
75 priority = 2*DEF_PRIORITY - priority;
76 if (!priority)
77 priority = 1;
78 }
79
80 for_each_task(p) {
81 if (!proc_sel(p, which, who))
82 continue;
83 if (p->uid != current->euid &&
84 p->uid != current->uid && !suser()) {
85 error = EPERM;
86 continue;
87 }
88 if (error == ESRCH)
89 error = 0;
90 if (priority > p->priority && !suser())
91 error = EACCES;
92 else
93 p->priority = priority;
94 }
95 return -error;
96 }
97
98
99
100
101
102
103 asmlinkage int sys_getpriority(int which, int who)
104 {
105 struct task_struct *p;
106 long max_prio = -ESRCH;
107
108 if (which > 2 || which < 0)
109 return -EINVAL;
110
111 for_each_task (p) {
112 if (!proc_sel(p, which, who))
113 continue;
114 if (p->priority > max_prio)
115 max_prio = p->priority;
116 }
117
118
119 if (max_prio > 0)
120 max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY;
121 return max_prio;
122 }
123
124 #ifndef __alpha__
125
126
127
128
129
130
131
132 asmlinkage int sys_profil(void)
133 {
134 return -ENOSYS;
135 }
136
137 asmlinkage int sys_ftime(void)
138 {
139 return -ENOSYS;
140 }
141
142 asmlinkage int sys_break(void)
143 {
144 return -ENOSYS;
145 }
146
147 asmlinkage int sys_stty(void)
148 {
149 return -ENOSYS;
150 }
151
152 asmlinkage int sys_gtty(void)
153 {
154 return -ENOSYS;
155 }
156
157 asmlinkage int sys_prof(void)
158 {
159 return -ENOSYS;
160 }
161
162 #endif
163
164 extern void hard_reset_now(void);
165 extern asmlinkage sys_kill(int, int);
166
167
168
169
170
171
172
173
174
175 asmlinkage int sys_reboot(int magic, int magic_too, int flag)
176 {
177 if (!suser())
178 return -EPERM;
179 if (magic != 0xfee1dead || magic_too != 672274793)
180 return -EINVAL;
181 if (flag == 0x01234567)
182 hard_reset_now();
183 else if (flag == 0x89ABCDEF)
184 C_A_D = 1;
185 else if (!flag)
186 C_A_D = 0;
187 else if (flag == 0xCDEF0123) {
188 printk(KERN_EMERG "System halted\n");
189 sys_kill(-1, SIGKILL);
190 do_exit(0);
191 } else
192 return -EINVAL;
193 return (0);
194 }
195
196
197
198
199
200
201 void ctrl_alt_del(void)
202 {
203 if (C_A_D)
204 hard_reset_now();
205 else
206 kill_proc(1, SIGINT, 1);
207 }
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225 asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
226 {
227 int old_rgid = current->gid;
228 int old_egid = current->egid;
229
230 if (rgid != (gid_t) -1) {
231 if ((old_rgid == rgid) ||
232 (current->egid==rgid) ||
233 suser())
234 current->gid = rgid;
235 else
236 return(-EPERM);
237 }
238 if (egid != (gid_t) -1) {
239 if ((old_rgid == egid) ||
240 (current->egid == egid) ||
241 (current->sgid == egid) ||
242 suser())
243 current->egid = egid;
244 else {
245 current->gid = old_rgid;
246 return(-EPERM);
247 }
248 }
249 if (rgid != (gid_t) -1 ||
250 (egid != (gid_t) -1 && egid != old_rgid))
251 current->sgid = current->egid;
252 current->fsgid = current->egid;
253 if (current->egid != old_egid)
254 current->dumpable = 0;
255 return 0;
256 }
257
258
259
260
261 asmlinkage int sys_setgid(gid_t gid)
262 {
263 int old_egid = current->egid;
264
265 if (suser())
266 current->gid = current->egid = current->sgid = current->fsgid = gid;
267 else if ((gid == current->gid) || (gid == current->sgid))
268 current->egid = current->fsgid = gid;
269 else
270 return -EPERM;
271 if (current->egid != old_egid)
272 current->dumpable = 0;
273 return 0;
274 }
275
276 asmlinkage int sys_acct(void)
277 {
278 return -ENOSYS;
279 }
280
281 #ifndef __alpha__
282
283
284
285
286
287
288
289 asmlinkage int sys_phys(void)
290 {
291 return -ENOSYS;
292 }
293
294 asmlinkage int sys_lock(void)
295 {
296 return -ENOSYS;
297 }
298
299 asmlinkage int sys_mpx(void)
300 {
301 return -ENOSYS;
302 }
303
304 asmlinkage int sys_ulimit(void)
305 {
306 return -ENOSYS;
307 }
308
309 asmlinkage int sys_old_syscall(void)
310 {
311 return -ENOSYS;
312 }
313
314 #endif
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331 asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
332 {
333 int old_ruid = current->uid;
334 int old_euid = current->euid;
335
336 if (ruid != (uid_t) -1) {
337 if ((old_ruid == ruid) ||
338 (current->euid==ruid) ||
339 suser())
340 current->uid = ruid;
341 else
342 return(-EPERM);
343 }
344 if (euid != (uid_t) -1) {
345 if ((old_ruid == euid) ||
346 (current->euid == euid) ||
347 (current->suid == euid) ||
348 suser())
349 current->euid = euid;
350 else {
351 current->uid = old_ruid;
352 return(-EPERM);
353 }
354 }
355 if (ruid != (uid_t) -1 ||
356 (euid != (uid_t) -1 && euid != old_ruid))
357 current->suid = current->euid;
358 current->fsuid = current->euid;
359 if (current->euid != old_euid)
360 current->dumpable = 0;
361 return 0;
362 }
363
364
365
366
367
368
369
370
371
372
373
374
375 asmlinkage int sys_setuid(uid_t uid)
376 {
377 int old_euid = current->euid;
378
379 if (suser())
380 current->uid = current->euid = current->suid = current->fsuid = uid;
381 else if ((uid == current->uid) || (uid == current->suid))
382 current->fsuid = current->euid = uid;
383 else
384 return -EPERM;
385 if (current->euid != old_euid)
386 current->dumpable = 0;
387 return(0);
388 }
389
390
391
392
393
394
395
396 asmlinkage int sys_setfsuid(uid_t uid)
397 {
398 int old_fsuid = current->fsuid;
399
400 if (uid == current->uid || uid == current->euid ||
401 uid == current->suid || uid == current->fsuid || suser())
402 current->fsuid = uid;
403 if (current->fsuid != old_fsuid)
404 current->dumpable = 0;
405 return old_fsuid;
406 }
407
408
409
410
411 asmlinkage int sys_setfsgid(gid_t gid)
412 {
413 int old_fsgid = current->fsgid;
414
415 if (gid == current->gid || gid == current->egid ||
416 gid == current->sgid || gid == current->fsgid || suser())
417 current->fsgid = gid;
418 if (current->fsgid != old_fsgid)
419 current->dumpable = 0;
420 return old_fsgid;
421 }
422
423 asmlinkage long sys_times(struct tms * tbuf)
424 {
425 if (tbuf) {
426 int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
427 if (error)
428 return error;
429 put_user(current->utime,&tbuf->tms_utime);
430 put_user(current->stime,&tbuf->tms_stime);
431 put_user(current->cutime,&tbuf->tms_cutime);
432 put_user(current->cstime,&tbuf->tms_cstime);
433 }
434 return jiffies;
435 }
436
437 asmlinkage unsigned long sys_brk(unsigned long brk)
438 {
439 int freepages;
440 unsigned long rlim;
441 unsigned long newbrk, oldbrk;
442
443 if (brk < current->mm->end_code)
444 return current->mm->brk;
445 newbrk = PAGE_ALIGN(brk);
446 oldbrk = PAGE_ALIGN(current->mm->brk);
447 if (oldbrk == newbrk)
448 return current->mm->brk = brk;
449
450
451
452
453 if (brk <= current->mm->brk) {
454 current->mm->brk = brk;
455 do_munmap(newbrk, oldbrk-newbrk);
456 return brk;
457 }
458
459
460
461 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
462 if (rlim >= RLIM_INFINITY)
463 rlim = ~0;
464 if (brk - current->mm->end_code > rlim)
465 return current->mm->brk;
466
467
468
469 if (find_vma_intersection(current, oldbrk, newbrk+PAGE_SIZE))
470 return current->mm->brk;
471
472
473
474
475
476 freepages = buffermem >> PAGE_SHIFT;
477 freepages += page_cache_size;
478 freepages >>= 1;
479 freepages += nr_free_pages;
480 freepages += nr_swap_pages;
481 freepages -= MAP_NR(high_memory) >> 4;
482 freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
483 if (freepages < 0)
484 return current->mm->brk;
485 #if 0
486 freepages += current->mm->rss;
487 freepages -= oldbrk >> 12;
488 if (freepages < 0)
489 return current->mm->brk;
490 #endif
491
492
493
494 current->mm->brk = brk;
495 do_mmap(NULL, oldbrk, newbrk-oldbrk,
496 PROT_READ|PROT_WRITE|PROT_EXEC,
497 MAP_FIXED|MAP_PRIVATE, 0);
498 return brk;
499 }
500
501
502
503
504
505
506
507
508
509
510
511
512
513 asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
514 {
515 struct task_struct * p;
516
517 if (!pid)
518 pid = current->pid;
519 if (!pgid)
520 pgid = pid;
521 if (pgid < 0)
522 return -EINVAL;
523 for_each_task(p) {
524 if (p->pid == pid)
525 goto found_task;
526 }
527 return -ESRCH;
528
529 found_task:
530 if (p->p_pptr == current || p->p_opptr == current) {
531 if (p->session != current->session)
532 return -EPERM;
533 if (p->did_exec)
534 return -EACCES;
535 } else if (p != current)
536 return -ESRCH;
537 if (p->leader)
538 return -EPERM;
539 if (pgid != pid) {
540 struct task_struct * tmp;
541 for_each_task (tmp) {
542 if (tmp->pgrp == pgid &&
543 tmp->session == current->session)
544 goto ok_pgid;
545 }
546 return -EPERM;
547 }
548
549 ok_pgid:
550 p->pgrp = pgid;
551 return 0;
552 }
553
554 asmlinkage int sys_getpgid(pid_t pid)
555 {
556 struct task_struct * p;
557
558 if (!pid)
559 return current->pgrp;
560 for_each_task(p) {
561 if (p->pid == pid)
562 return p->pgrp;
563 }
564 return -ESRCH;
565 }
566
567 asmlinkage int sys_getpgrp(void)
568 {
569 return current->pgrp;
570 }
571
572 asmlinkage int sys_getsid(pid_t pid)
573 {
574 struct task_struct * p;
575
576 if (!pid)
577 return current->session;
578 for_each_task(p) {
579 if (p->pid == pid)
580 return p->session;
581 }
582 return -ESRCH;
583 }
584
585 asmlinkage int sys_setsid(void)
586 {
587 if (current->leader)
588 return -EPERM;
589 current->leader = 1;
590 current->session = current->pgrp = current->pid;
591 current->tty = NULL;
592 current->tty_old_pgrp = 0;
593 return current->pgrp;
594 }
595
596
597
598
599 asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
600 {
601 int i;
602 int * groups;
603
604 if (gidsetsize) {
605 i = verify_area(VERIFY_WRITE, grouplist, sizeof(gid_t) * gidsetsize);
606 if (i)
607 return i;
608 }
609 groups = current->groups;
610 for (i = 0 ; (i < NGROUPS) && (*groups != NOGROUP) ; i++, groups++) {
611 if (!gidsetsize)
612 continue;
613 if (i >= gidsetsize)
614 break;
615 put_user(*groups, grouplist);
616 grouplist++;
617 }
618 return(i);
619 }
620
621 asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
622 {
623 int i;
624
625 if (!suser())
626 return -EPERM;
627 if (gidsetsize > NGROUPS)
628 return -EINVAL;
629 i = verify_area(VERIFY_READ, grouplist, sizeof(gid_t) * gidsetsize);
630 if (i)
631 return i;
632 for (i = 0; i < gidsetsize; i++, grouplist++) {
633 current->groups[i] = get_user(grouplist);
634 }
635 if (i < NGROUPS)
636 current->groups[i] = NOGROUP;
637 return 0;
638 }
639
640 int in_group_p(gid_t grp)
641 {
642 int i;
643
644 if (grp == current->fsgid)
645 return 1;
646
647 for (i = 0; i < NGROUPS; i++) {
648 if (current->groups[i] == NOGROUP)
649 break;
650 if (current->groups[i] == grp)
651 return 1;
652 }
653 return 0;
654 }
655
656 asmlinkage int sys_newuname(struct new_utsname * name)
657 {
658 int error;
659
660 if (!name)
661 return -EFAULT;
662 error = verify_area(VERIFY_WRITE, name, sizeof *name);
663 if (!error)
664 memcpy_tofs(name,&system_utsname,sizeof *name);
665 return error;
666 }
667
668 #ifndef __alpha__
669
670
671
672
673
674 asmlinkage int sys_uname(struct old_utsname * name)
675 {
676 int error;
677 if (!name)
678 return -EFAULT;
679 error = verify_area(VERIFY_WRITE, name,sizeof *name);
680 if (error)
681 return error;
682 memcpy_tofs(&name->sysname,&system_utsname.sysname,
683 sizeof (system_utsname.sysname));
684 memcpy_tofs(&name->nodename,&system_utsname.nodename,
685 sizeof (system_utsname.nodename));
686 memcpy_tofs(&name->release,&system_utsname.release,
687 sizeof (system_utsname.release));
688 memcpy_tofs(&name->version,&system_utsname.version,
689 sizeof (system_utsname.version));
690 memcpy_tofs(&name->machine,&system_utsname.machine,
691 sizeof (system_utsname.machine));
692 return 0;
693 }
694
695 asmlinkage int sys_olduname(struct oldold_utsname * name)
696 {
697 int error;
698 if (!name)
699 return -EFAULT;
700 error = verify_area(VERIFY_WRITE, name,sizeof *name);
701 if (error)
702 return error;
703 memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
704 put_user(0,name->sysname+__OLD_UTS_LEN);
705 memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
706 put_user(0,name->nodename+__OLD_UTS_LEN);
707 memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN);
708 put_user(0,name->release+__OLD_UTS_LEN);
709 memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN);
710 put_user(0,name->version+__OLD_UTS_LEN);
711 memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
712 put_user(0,name->machine+__OLD_UTS_LEN);
713 return 0;
714 }
715
716 #endif
717
718 asmlinkage int sys_sethostname(char *name, int len)
719 {
720 int error;
721
722 if (!suser())
723 return -EPERM;
724 if (len < 0 || len > __NEW_UTS_LEN)
725 return -EINVAL;
726 error = verify_area(VERIFY_READ, name, len);
727 if (error)
728 return error;
729 memcpy_fromfs(system_utsname.nodename, name, len);
730 system_utsname.nodename[len] = 0;
731 return 0;
732 }
733
734 asmlinkage int sys_gethostname(char *name, int len)
735 {
736 int i;
737
738 if (len < 0)
739 return -EINVAL;
740 i = verify_area(VERIFY_WRITE, name, len);
741 if (i)
742 return i;
743 i = 1+strlen(system_utsname.nodename);
744 if (i > len)
745 i = len;
746 memcpy_tofs(name, system_utsname.nodename, i);
747 return 0;
748 }
749
750
751
752
753
754 asmlinkage int sys_setdomainname(char *name, int len)
755 {
756 int error;
757
758 if (!suser())
759 return -EPERM;
760 if (len < 0 || len > __NEW_UTS_LEN)
761 return -EINVAL;
762 error = verify_area(VERIFY_READ, name, len);
763 if (error)
764 return error;
765 memcpy_fromfs(system_utsname.domainname, name, len);
766 system_utsname.domainname[len] = 0;
767 return 0;
768 }
769
770 asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
771 {
772 int error;
773
774 if (resource >= RLIM_NLIMITS)
775 return -EINVAL;
776 error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
777 if (error)
778 return error;
779 memcpy_tofs(rlim, current->rlim + resource, sizeof(*rlim));
780 return 0;
781 }
782
783 asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
784 {
785 struct rlimit new_rlim, *old_rlim;
786 int err;
787
788 if (resource >= RLIM_NLIMITS)
789 return -EINVAL;
790 err = verify_area(VERIFY_READ, rlim, sizeof(*rlim));
791 if (err)
792 return err;
793 memcpy_fromfs(&new_rlim, rlim, sizeof(*rlim));
794 old_rlim = current->rlim + resource;
795 if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
796 (new_rlim.rlim_max > old_rlim->rlim_max)) &&
797 !suser())
798 return -EPERM;
799 if (resource == RLIMIT_NOFILE) {
800 if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
801 return -EPERM;
802 }
803 *old_rlim = new_rlim;
804 return 0;
805 }
806
807
808
809
810
811
812
813
814
815 int getrusage(struct task_struct *p, int who, struct rusage *ru)
816 {
817 int error;
818 struct rusage r;
819
820 error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
821 if (error)
822 return error;
823 memset((char *) &r, 0, sizeof(r));
824 switch (who) {
825 case RUSAGE_SELF:
826 r.ru_utime.tv_sec = CT_TO_SECS(p->utime);
827 r.ru_utime.tv_usec = CT_TO_USECS(p->utime);
828 r.ru_stime.tv_sec = CT_TO_SECS(p->stime);
829 r.ru_stime.tv_usec = CT_TO_USECS(p->stime);
830 r.ru_minflt = p->min_flt;
831 r.ru_majflt = p->maj_flt;
832 r.ru_nswap = p->nswap;
833 break;
834 case RUSAGE_CHILDREN:
835 r.ru_utime.tv_sec = CT_TO_SECS(p->cutime);
836 r.ru_utime.tv_usec = CT_TO_USECS(p->cutime);
837 r.ru_stime.tv_sec = CT_TO_SECS(p->cstime);
838 r.ru_stime.tv_usec = CT_TO_USECS(p->cstime);
839 r.ru_minflt = p->cmin_flt;
840 r.ru_majflt = p->cmaj_flt;
841 r.ru_nswap = p->cnswap;
842 break;
843 default:
844 r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime);
845 r.ru_utime.tv_usec = CT_TO_USECS(p->utime + p->cutime);
846 r.ru_stime.tv_sec = CT_TO_SECS(p->stime + p->cstime);
847 r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime);
848 r.ru_minflt = p->min_flt + p->cmin_flt;
849 r.ru_majflt = p->maj_flt + p->cmaj_flt;
850 r.ru_nswap = p->nswap + p->cnswap;
851 break;
852 }
853 memcpy_tofs(ru, &r, sizeof(r));
854 return 0;
855 }
856
857 asmlinkage int sys_getrusage(int who, struct rusage *ru)
858 {
859 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
860 return -EINVAL;
861 return getrusage(current, who, ru);
862 }
863
864 asmlinkage int sys_umask(int mask)
865 {
866 int old = current->fs->umask;
867
868 current->fs->umask = mask & S_IRWXUGO;
869 return (old);
870 }