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 int error;
170
171 if (current->saved_kernel_stack)
172 return -EPERM;
173
174 error = verify_area(VERIFY_WRITE,v86,sizeof(*v86));
175 if (error)
176 return error;
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 |= ~0x00000dd5 & 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"
202 :
203 :"g" ((long) &(info.regs)),"a" (info.regs.eax));
204 return 0;
205 }
206
207 extern void hard_reset_now(void);
208
209
210
211
212
213
214
215
216
217 asmlinkage int sys_reboot(int magic, int magic_too, int flag)
218 {
219 if (!suser())
220 return -EPERM;
221 if (magic != 0xfee1dead || magic_too != 672274793)
222 return -EINVAL;
223 if (flag == 0x01234567)
224 hard_reset_now();
225 else if (flag == 0x89ABCDEF)
226 C_A_D = 1;
227 else if (!flag)
228 C_A_D = 0;
229 else
230 return -EINVAL;
231 return (0);
232 }
233
234
235
236
237
238
239 void ctrl_alt_del(void)
240 {
241 if (C_A_D)
242 hard_reset_now();
243 else
244 send_sig(SIGINT,task[1],1);
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259 asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
260 {
261 int old_rgid = current->gid;
262
263 if (rgid != (gid_t) -1) {
264 if ((current->egid==rgid) ||
265 (old_rgid == rgid) ||
266 suser())
267 current->gid = rgid;
268 else
269 return(-EPERM);
270 }
271 if (egid != (gid_t) -1) {
272 if ((old_rgid == egid) ||
273 (current->egid == egid) ||
274 suser()) {
275 current->egid = egid;
276 current->sgid = egid;
277 } else {
278 current->gid = old_rgid;
279 return(-EPERM);
280 }
281 }
282 return 0;
283 }
284
285
286
287
288 asmlinkage int sys_setgid(gid_t gid)
289 {
290 if (suser())
291 current->gid = current->egid = current->sgid = gid;
292 else if ((gid == current->gid) || (gid == current->sgid))
293 current->egid = gid;
294 else
295 return -EPERM;
296 return 0;
297 }
298
299 asmlinkage int sys_acct(void)
300 {
301 return -ENOSYS;
302 }
303
304 asmlinkage int sys_phys(void)
305 {
306 return -ENOSYS;
307 }
308
309 asmlinkage int sys_lock(void)
310 {
311 return -ENOSYS;
312 }
313
314 asmlinkage int sys_mpx(void)
315 {
316 return -ENOSYS;
317 }
318
319 asmlinkage int sys_ulimit(void)
320 {
321 return -ENOSYS;
322 }
323
324 asmlinkage int sys_old_syscall(void)
325 {
326 return -ENOSYS;
327 }
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342 asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
343 {
344 int old_ruid = current->uid;
345
346 if (ruid != (uid_t) -1) {
347 if ((current->euid==ruid) ||
348 (old_ruid == ruid) ||
349 suser())
350 current->uid = ruid;
351 else
352 return(-EPERM);
353 }
354 if (euid != (uid_t) -1) {
355 if ((old_ruid == euid) ||
356 (current->euid == euid) ||
357 suser()) {
358 current->euid = euid;
359 current->suid = euid;
360 } else {
361 current->uid = old_ruid;
362 return(-EPERM);
363 }
364 }
365 return 0;
366 }
367
368
369
370
371
372
373
374
375
376
377
378
379 asmlinkage int sys_setuid(uid_t uid)
380 {
381 if (suser())
382 current->uid = current->euid = current->suid = uid;
383 else if ((uid == current->uid) || (uid == current->suid))
384 current->euid = uid;
385 else
386 return -EPERM;
387 return(0);
388 }
389
390 asmlinkage int sys_times(struct tms * tbuf)
391 {
392 if (tbuf) {
393 int error = verify_area(VERIFY_WRITE,tbuf,sizeof *tbuf);
394 if (error)
395 return error;
396 put_fs_long(current->utime,(unsigned long *)&tbuf->tms_utime);
397 put_fs_long(current->stime,(unsigned long *)&tbuf->tms_stime);
398 put_fs_long(current->cutime,(unsigned long *)&tbuf->tms_cutime);
399 put_fs_long(current->cstime,(unsigned long *)&tbuf->tms_cstime);
400 }
401 return jiffies;
402 }
403
404 asmlinkage int sys_brk(unsigned long brk)
405 {
406 int freepages;
407 unsigned long rlim;
408 unsigned long newbrk, oldbrk;
409
410 if (brk < current->end_code)
411 return current->brk;
412 newbrk = PAGE_ALIGN(brk);
413 oldbrk = PAGE_ALIGN(current->brk);
414 if (oldbrk == newbrk)
415 return current->brk = brk;
416
417
418
419
420 if (brk <= current->brk) {
421 current->brk = brk;
422 do_munmap(newbrk, oldbrk-newbrk);
423 return brk;
424 }
425
426
427
428 rlim = current->rlim[RLIMIT_DATA].rlim_cur;
429 if (rlim >= RLIM_INFINITY)
430 rlim = ~0;
431 if (brk - current->end_code > rlim || brk >= current->start_stack - 16384)
432 return current->brk;
433
434
435
436
437
438 freepages = buffermem >> 12;
439 freepages += nr_free_pages;
440 freepages += nr_swap_pages;
441 freepages -= (high_memory - 0x100000) >> 16;
442 freepages -= (newbrk-oldbrk) >> 12;
443 if (freepages < 0)
444 return current->brk;
445 #if 0
446 freepages += current->rss;
447 freepages -= oldbrk >> 12;
448 if (freepages < 0)
449 return current->brk;
450 #endif
451
452
453
454 current->brk = brk;
455 do_mmap(NULL, oldbrk, newbrk-oldbrk,
456 PROT_READ|PROT_WRITE|PROT_EXEC,
457 MAP_FIXED|MAP_PRIVATE, 0);
458 return brk;
459 }
460
461
462
463
464
465
466
467
468
469
470
471
472
473 asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
474 {
475 struct task_struct * p;
476
477 if (!pid)
478 pid = current->pid;
479 if (!pgid)
480 pgid = pid;
481 if (pgid < 0)
482 return -EINVAL;
483 for_each_task(p) {
484 if (p->pid == pid)
485 goto found_task;
486 }
487 return -ESRCH;
488
489 found_task:
490 if (p->p_pptr == current || p->p_opptr == current) {
491 if (p->session != current->session)
492 return -EPERM;
493 if (p->did_exec)
494 return -EACCES;
495 } else if (p != current)
496 return -ESRCH;
497 if (p->leader)
498 return -EPERM;
499 if (pgid != pid) {
500 struct task_struct * tmp;
501 for_each_task (tmp) {
502 if (tmp->pgrp == pgid &&
503 tmp->session == current->session)
504 goto ok_pgid;
505 }
506 return -EPERM;
507 }
508
509 ok_pgid:
510 p->pgrp = pgid;
511 return 0;
512 }
513
514 asmlinkage int sys_getpgid(pid_t pid)
515 {
516 struct task_struct * p;
517
518 if (!pid)
519 return current->pgrp;
520 for_each_task(p) {
521 if (p->pid == pid)
522 return p->pgrp;
523 }
524 return -ESRCH;
525 }
526
527 asmlinkage int sys_getpgrp(void)
528 {
529 return current->pgrp;
530 }
531
532 asmlinkage int sys_setsid(void)
533 {
534 if (current->leader)
535 return -EPERM;
536 current->leader = 1;
537 current->session = current->pgrp = current->pid;
538 current->tty = -1;
539 return current->pgrp;
540 }
541
542
543
544
545 asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
546 {
547 int i;
548
549 if (gidsetsize) {
550 i = verify_area(VERIFY_WRITE, grouplist, sizeof(gid_t) * gidsetsize);
551 if (i)
552 return i;
553 }
554 for (i = 0 ; (i < NGROUPS) && (current->groups[i] != NOGROUP) ; i++) {
555 if (!gidsetsize)
556 continue;
557 if (i >= gidsetsize)
558 break;
559 put_fs_word(current->groups[i], (short *) grouplist);
560 grouplist++;
561 }
562 return(i);
563 }
564
565 asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
566 {
567 int i;
568
569 if (!suser())
570 return -EPERM;
571 if (gidsetsize > NGROUPS)
572 return -EINVAL;
573 for (i = 0; i < gidsetsize; i++, grouplist++) {
574 current->groups[i] = get_fs_word((unsigned short *) grouplist);
575 }
576 if (i < NGROUPS)
577 current->groups[i] = NOGROUP;
578 return 0;
579 }
580
581 int in_group_p(gid_t grp)
582 {
583 int i;
584
585 if (grp == current->egid)
586 return 1;
587
588 for (i = 0; i < NGROUPS; i++) {
589 if (current->groups[i] == NOGROUP)
590 break;
591 if (current->groups[i] == grp)
592 return 1;
593 }
594 return 0;
595 }
596
597 asmlinkage int sys_newuname(struct new_utsname * name)
598 {
599 int error;
600
601 if (!name)
602 return -EFAULT;
603 error = verify_area(VERIFY_WRITE, name, sizeof *name);
604 if (!error)
605 memcpy_tofs(name,&system_utsname,sizeof *name);
606 return error;
607 }
608
609 asmlinkage int sys_uname(struct old_utsname * name)
610 {
611 int error;
612 if (!name)
613 return -EFAULT;
614 error = verify_area(VERIFY_WRITE, name,sizeof *name);
615 if (error)
616 return error;
617 memcpy_tofs(&name->sysname,&system_utsname.sysname,
618 sizeof (system_utsname.sysname));
619 memcpy_tofs(&name->nodename,&system_utsname.nodename,
620 sizeof (system_utsname.nodename));
621 memcpy_tofs(&name->release,&system_utsname.release,
622 sizeof (system_utsname.release));
623 memcpy_tofs(&name->version,&system_utsname.version,
624 sizeof (system_utsname.version));
625 memcpy_tofs(&name->machine,&system_utsname.machine,
626 sizeof (system_utsname.machine));
627 return 0;
628 }
629
630 asmlinkage int sys_olduname(struct oldold_utsname * name)
631 {
632 int error;
633 if (!name)
634 return -EFAULT;
635 error = verify_area(VERIFY_WRITE, name,sizeof *name);
636 if (error)
637 return error;
638 memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
639 put_fs_byte(0,name->sysname+__OLD_UTS_LEN);
640 memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
641 put_fs_byte(0,name->nodename+__OLD_UTS_LEN);
642 memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN);
643 put_fs_byte(0,name->release+__OLD_UTS_LEN);
644 memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN);
645 put_fs_byte(0,name->version+__OLD_UTS_LEN);
646 memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
647 put_fs_byte(0,name->machine+__OLD_UTS_LEN);
648 return 0;
649 }
650
651
652
653
654 asmlinkage int sys_sethostname(char *name, int len)
655 {
656 int i;
657
658 if (!suser())
659 return -EPERM;
660 if (len > __NEW_UTS_LEN)
661 return -EINVAL;
662 for (i=0; i < len; i++) {
663 if ((system_utsname.nodename[i] = get_fs_byte(name+i)) == 0)
664 return 0;
665 }
666 system_utsname.nodename[i] = 0;
667 return 0;
668 }
669
670
671
672
673
674 asmlinkage int sys_setdomainname(char *name, int len)
675 {
676 int i;
677
678 if (!suser())
679 return -EPERM;
680 if (len > __NEW_UTS_LEN)
681 return -EINVAL;
682 for (i=0; i < len; i++) {
683 if ((system_utsname.domainname[i] = get_fs_byte(name+i)) == 0)
684 return 0;
685 }
686 system_utsname.domainname[i] = 0;
687 return 0;
688 }
689
690 asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
691 {
692 int error;
693
694 if (resource >= RLIM_NLIMITS)
695 return -EINVAL;
696 error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
697 if (error)
698 return error;
699 put_fs_long(current->rlim[resource].rlim_cur,
700 (unsigned long *) rlim);
701 put_fs_long(current->rlim[resource].rlim_max,
702 ((unsigned long *) rlim)+1);
703 return 0;
704 }
705
706 asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
707 {
708 struct rlimit new_rlim, *old_rlim;
709
710 if (resource >= RLIM_NLIMITS)
711 return -EINVAL;
712 old_rlim = current->rlim + resource;
713 new_rlim.rlim_cur = get_fs_long((unsigned long *) rlim);
714 new_rlim.rlim_max = get_fs_long(((unsigned long *) rlim)+1);
715 if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
716 (new_rlim.rlim_max > old_rlim->rlim_max)) &&
717 !suser())
718 return -EPERM;
719 *old_rlim = new_rlim;
720 return 0;
721 }
722
723
724
725
726
727
728
729
730
731 int getrusage(struct task_struct *p, int who, struct rusage *ru)
732 {
733 int error;
734 struct rusage r;
735 unsigned long *lp, *lpend, *dest;
736
737 error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
738 if (error)
739 return error;
740 memset((char *) &r, 0, sizeof(r));
741 switch (who) {
742 case RUSAGE_SELF:
743 r.ru_utime.tv_sec = CT_TO_SECS(p->utime);
744 r.ru_utime.tv_usec = CT_TO_USECS(p->utime);
745 r.ru_stime.tv_sec = CT_TO_SECS(p->stime);
746 r.ru_stime.tv_usec = CT_TO_USECS(p->stime);
747 r.ru_minflt = p->min_flt;
748 r.ru_majflt = p->maj_flt;
749 break;
750 case RUSAGE_CHILDREN:
751 r.ru_utime.tv_sec = CT_TO_SECS(p->cutime);
752 r.ru_utime.tv_usec = CT_TO_USECS(p->cutime);
753 r.ru_stime.tv_sec = CT_TO_SECS(p->cstime);
754 r.ru_stime.tv_usec = CT_TO_USECS(p->cstime);
755 r.ru_minflt = p->cmin_flt;
756 r.ru_majflt = p->cmaj_flt;
757 break;
758 default:
759 r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime);
760 r.ru_utime.tv_usec = CT_TO_USECS(p->utime + p->cutime);
761 r.ru_stime.tv_sec = CT_TO_SECS(p->stime + p->cstime);
762 r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime);
763 r.ru_minflt = p->min_flt + p->cmin_flt;
764 r.ru_majflt = p->maj_flt + p->cmaj_flt;
765 break;
766 }
767 lp = (unsigned long *) &r;
768 lpend = (unsigned long *) (&r+1);
769 dest = (unsigned long *) ru;
770 for (; lp < lpend; lp++, dest++)
771 put_fs_long(*lp, dest);
772 return 0;
773 }
774
775 asmlinkage int sys_getrusage(int who, struct rusage *ru)
776 {
777 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
778 return -EINVAL;
779 return getrusage(current, who, ru);
780 }
781
782 asmlinkage int sys_umask(int mask)
783 {
784 int old = current->umask;
785
786 current->umask = mask & S_IRWXUGO;
787 return (old);
788 }