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