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