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