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