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