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_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_olduname
- sys_sethostname
- sys_setdomainname
- 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 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 &= 0xfffff000;
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 int sys_vm86(struct vm86_struct * v86)
171 {
172 struct vm86_struct info;
173 struct pt_regs * pt_regs = (struct pt_regs *) &v86;
174
175 if (current->saved_kernel_stack)
176 return -EPERM;
177 memcpy_fromfs(&info,v86,sizeof(info));
178
179
180
181 info.regs.__null_ds = 0;
182 info.regs.__null_es = 0;
183 info.regs.__null_fs = 0;
184 info.regs.__null_gs = 0;
185
186
187
188
189
190 info.regs.eflags &= 0x00000dd5;
191 info.regs.eflags |= 0xfffff22a & pt_regs->eflags;
192 info.regs.eflags |= VM_MASK;
193 current->saved_kernel_stack = current->tss.esp0;
194 current->tss.esp0 = (unsigned long) pt_regs;
195 current->vm86_info = v86;
196 current->screen_bitmap = info.screen_bitmap;
197 if (info.flags & VM86_SCREEN_BITMAP)
198 mark_screen_rdonly(current);
199 __asm__ __volatile__("movl %0,%%esp\n\t"
200 "pushl $ret_from_sys_call\n\t"
201 "ret"::"g" ((long) &(info.regs)),"a" (info.regs.eax));
202 return 0;
203 }
204
205 extern void hard_reset_now(void);
206
207
208
209
210
211
212
213
214
215 int sys_reboot(int magic, int magic_too, int flag)
216 {
217 if (!suser())
218 return -EPERM;
219 if (magic != 0xfee1dead || magic_too != 672274793)
220 return -EINVAL;
221 if (flag == 0x01234567)
222 hard_reset_now();
223 else if (flag == 0x89ABCDEF)
224 C_A_D = 1;
225 else if (!flag)
226 C_A_D = 0;
227 else
228 return -EINVAL;
229 return (0);
230 }
231
232
233
234
235
236
237 void ctrl_alt_del(void)
238 {
239 if (C_A_D)
240 hard_reset_now();
241 else
242 send_sig(SIGINT,task[1],1);
243 }
244
245
246
247
248
249
250
251
252
253
254
255
256
257 int sys_setregid(gid_t rgid, gid_t egid)
258 {
259 int old_rgid = current->gid;
260
261 if (rgid != (gid_t) -1) {
262 if ((current->egid==rgid) ||
263 (old_rgid == rgid) ||
264 suser())
265 current->gid = rgid;
266 else
267 return(-EPERM);
268 }
269 if (egid != (gid_t) -1) {
270 if ((old_rgid == egid) ||
271 (current->egid == egid) ||
272 suser()) {
273 current->egid = egid;
274 current->sgid = egid;
275 } else {
276 current->gid = old_rgid;
277 return(-EPERM);
278 }
279 }
280 return 0;
281 }
282
283
284
285
286 int sys_setgid(gid_t gid)
287 {
288 if (suser())
289 current->gid = current->egid = current->sgid = gid;
290 else if ((gid == current->gid) || (gid == current->sgid))
291 current->egid = gid;
292 else
293 return -EPERM;
294 return 0;
295 }
296
297 int sys_acct(void)
298 {
299 return -ENOSYS;
300 }
301
302 int sys_phys(void)
303 {
304 return -ENOSYS;
305 }
306
307 int sys_lock(void)
308 {
309 return -ENOSYS;
310 }
311
312 int sys_mpx(void)
313 {
314 return -ENOSYS;
315 }
316
317 int sys_ulimit(void)
318 {
319 return -ENOSYS;
320 }
321
322 int sys_old_syscall(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,
576 sizeof (system_utsname.sysname));
577 memcpy_tofs(&name->nodename,&system_utsname.nodename,
578 sizeof (system_utsname.nodename));
579 memcpy_tofs(&name->release,&system_utsname.release,
580 sizeof (system_utsname.release));
581 memcpy_tofs(&name->version,&system_utsname.version,
582 sizeof (system_utsname.version));
583 memcpy_tofs(&name->machine,&system_utsname.machine,
584 sizeof (system_utsname.machine));
585 return 0;
586 }
587
588 int sys_olduname(struct oldold_utsname * name)
589 {
590 int error;
591 if (!name)
592 return -EFAULT;
593 error = verify_area(VERIFY_WRITE, name,sizeof *name);
594 if (error)
595 return error;
596 memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
597 put_fs_byte(0,name->sysname+__OLD_UTS_LEN);
598 memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
599 put_fs_byte(0,name->nodename+__OLD_UTS_LEN);
600 memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN);
601 put_fs_byte(0,name->release+__OLD_UTS_LEN);
602 memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN);
603 put_fs_byte(0,name->version+__OLD_UTS_LEN);
604 memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
605 put_fs_byte(0,name->machine+__OLD_UTS_LEN);
606 return 0;
607 }
608
609
610
611
612 int sys_sethostname(char *name, int len)
613 {
614 int i;
615
616 if (!suser())
617 return -EPERM;
618 if (len > __NEW_UTS_LEN)
619 return -EINVAL;
620 for (i=0; i < len; i++) {
621 if ((system_utsname.nodename[i] = get_fs_byte(name+i)) == 0)
622 return 0;
623 }
624 system_utsname.nodename[i] = 0;
625 return 0;
626 }
627
628
629
630
631
632 int sys_setdomainname(char *name, int len)
633 {
634 int i;
635
636 if (!suser())
637 return -EPERM;
638 if (len > __NEW_UTS_LEN)
639 return -EINVAL;
640 for (i=0; i < len; i++) {
641 if ((system_utsname.domainname[i] = get_fs_byte(name+i)) == 0)
642 return 0;
643 }
644 system_utsname.domainname[i] = 0;
645 return 0;
646 }
647
648 int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
649 {
650 int error;
651
652 if (resource >= RLIM_NLIMITS)
653 return -EINVAL;
654 error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
655 if (error)
656 return error;
657 put_fs_long(current->rlim[resource].rlim_cur,
658 (unsigned long *) rlim);
659 put_fs_long(current->rlim[resource].rlim_max,
660 ((unsigned long *) rlim)+1);
661 return 0;
662 }
663
664 int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
665 {
666 struct rlimit new, *old;
667
668 if (resource >= RLIM_NLIMITS)
669 return -EINVAL;
670 old = current->rlim + resource;
671 new.rlim_cur = get_fs_long((unsigned long *) rlim);
672 new.rlim_max = get_fs_long(((unsigned long *) rlim)+1);
673 if (((new.rlim_cur > old->rlim_max) ||
674 (new.rlim_max > old->rlim_max)) &&
675 !suser())
676 return -EPERM;
677 *old = new;
678 return 0;
679 }
680
681
682
683
684
685
686
687
688
689 int getrusage(struct task_struct *p, int who, struct rusage *ru)
690 {
691 int error;
692 struct rusage r;
693 unsigned long *lp, *lpend, *dest;
694
695 error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
696 if (error)
697 return error;
698 memset((char *) &r, 0, sizeof(r));
699 switch (who) {
700 case RUSAGE_SELF:
701 r.ru_utime.tv_sec = CT_TO_SECS(p->utime);
702 r.ru_utime.tv_usec = CT_TO_USECS(p->utime);
703 r.ru_stime.tv_sec = CT_TO_SECS(p->stime);
704 r.ru_stime.tv_usec = CT_TO_USECS(p->stime);
705 r.ru_minflt = p->min_flt;
706 r.ru_majflt = p->maj_flt;
707 break;
708 case RUSAGE_CHILDREN:
709 r.ru_utime.tv_sec = CT_TO_SECS(p->cutime);
710 r.ru_utime.tv_usec = CT_TO_USECS(p->cutime);
711 r.ru_stime.tv_sec = CT_TO_SECS(p->cstime);
712 r.ru_stime.tv_usec = CT_TO_USECS(p->cstime);
713 r.ru_minflt = p->cmin_flt;
714 r.ru_majflt = p->cmaj_flt;
715 break;
716 default:
717 r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime);
718 r.ru_utime.tv_usec = CT_TO_USECS(p->utime + p->cutime);
719 r.ru_stime.tv_sec = CT_TO_SECS(p->stime + p->cstime);
720 r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime);
721 r.ru_minflt = p->min_flt + p->cmin_flt;
722 r.ru_majflt = p->maj_flt + p->cmaj_flt;
723 break;
724 }
725 lp = (unsigned long *) &r;
726 lpend = (unsigned long *) (&r+1);
727 dest = (unsigned long *) ru;
728 for (; lp < lpend; lp++, dest++)
729 put_fs_long(*lp, dest);
730 return 0;
731 }
732
733 int sys_getrusage(int who, struct rusage *ru)
734 {
735 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
736 return -EINVAL;
737 return getrusage(current, who, ru);
738 }
739
740 #define LATCH ((1193180 + HZ/2)/HZ)
741
742
743
744
745
746 static inline void do_gettimeofday(struct timeval *tv)
747 {
748 unsigned long nowtime;
749 long count;
750
751 #ifdef __i386__
752 cli();
753
754 outb_p(0x00, 0x43);
755 nowtime = jiffies;
756 count = inb_p(0x40);
757 count |= inb_p(0x40) << 8;
758
759 if (count < (LATCH - LATCH/100))
760 sti();
761 else {
762
763 outb_p(0x0a, 0x20);
764 if (inb(0x20) & 1)
765 nowtime++;
766 sti();
767 }
768 nowtime += jiffies_offset;
769 tv->tv_sec = startup_time + CT_TO_SECS(nowtime);
770
771 tv->tv_usec = CT_TO_USECS(nowtime)
772 + ((LATCH - 1) - count)*(1000000/HZ)/LATCH;
773 #else
774 nowtime = jiffies + jiffes_offset;
775 tv->tv_sec = startup_time + CT_TO_SECS(nowtime);
776 tv->tv_usec = CT_TO_USECS(nowtime);
777 #endif
778 }
779
780 int sys_gettimeofday(struct timeval *tv, struct timezone *tz)
781 {
782 int error;
783
784 if (tv) {
785 struct timeval ktv;
786 error = verify_area(VERIFY_WRITE, tv, sizeof *tv);
787 if (error)
788 return error;
789 do_gettimeofday(&ktv);
790 put_fs_long(ktv.tv_sec, &tv->tv_sec);
791 put_fs_long(ktv.tv_usec, &tv->tv_usec);
792 }
793 if (tz) {
794 error = verify_area(VERIFY_WRITE, tz, sizeof *tz);
795 if (error)
796 return error;
797 put_fs_long(sys_tz.tz_minuteswest, (unsigned long *) tz);
798 put_fs_long(sys_tz.tz_dsttime, ((unsigned long *) tz)+1);
799 }
800 return 0;
801 }
802
803
804
805
806
807
808
809
810
811
812 int sys_settimeofday(struct timeval *tv, struct timezone *tz)
813 {
814 static int firsttime = 1;
815 void adjust_clock(void);
816
817 if (!suser())
818 return -EPERM;
819 if (tz) {
820 sys_tz.tz_minuteswest = get_fs_long((unsigned long *) tz);
821 sys_tz.tz_dsttime = get_fs_long(((unsigned long *) tz)+1);
822 if (firsttime) {
823 firsttime = 0;
824 if (!tv)
825 adjust_clock();
826 }
827 }
828 if (tv) {
829 int sec, usec;
830
831 sec = get_fs_long((unsigned long *)tv);
832 usec = get_fs_long(((unsigned long *)tv)+1);
833
834 startup_time = sec - jiffies/HZ;
835 jiffies_offset = usec * HZ / 1000000 - jiffies%HZ;
836 }
837 return 0;
838 }
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856 void adjust_clock(void)
857 {
858 startup_time += sys_tz.tz_minuteswest*60;
859 }
860
861 int sys_umask(int mask)
862 {
863 int old = current->umask;
864
865 current->umask = mask & 0777;
866 return (old);
867 }
868