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