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 asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
466 {
467 int i;
468
469 if (!pid)
470 pid = current->pid;
471 if (!pgid)
472 pgid = current->pid;
473 if (pgid < 0)
474 return -EINVAL;
475 for (i=0 ; i<NR_TASKS ; i++)
476 if (task[i] && (task[i]->pid == pid) &&
477 ((task[i]->p_pptr == current) ||
478 (task[i]->p_opptr == current) ||
479 (task[i] == current))) {
480 if (task[i]->leader)
481 return -EPERM;
482 if ((task[i]->session != current->session) ||
483 ((pgid != pid) &&
484 (session_of_pgrp(pgid) != current->session)))
485 return -EPERM;
486 task[i]->pgrp = pgid;
487 return 0;
488 }
489 return -ESRCH;
490 }
491
492 asmlinkage int sys_getpgid(pid_t pid)
493 {
494 struct task_struct * p;
495
496 if (!pid)
497 return current->pgrp;
498 for_each_task(p) {
499 if (p->pid == pid)
500 return p->pgrp;
501 }
502 return -ESRCH;
503 }
504
505 asmlinkage int sys_getpgrp(void)
506 {
507 return current->pgrp;
508 }
509
510 asmlinkage int sys_setsid(void)
511 {
512 if (current->leader)
513 return -EPERM;
514 current->leader = 1;
515 current->session = current->pgrp = current->pid;
516 current->tty = -1;
517 return current->pgrp;
518 }
519
520
521
522
523 asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
524 {
525 int i;
526
527 if (gidsetsize) {
528 i = verify_area(VERIFY_WRITE, grouplist, sizeof(gid_t) * gidsetsize);
529 if (i)
530 return i;
531 }
532 for (i = 0 ; (i < NGROUPS) && (current->groups[i] != NOGROUP) ; i++) {
533 if (!gidsetsize)
534 continue;
535 if (i >= gidsetsize)
536 break;
537 put_fs_word(current->groups[i], (short *) grouplist);
538 grouplist++;
539 }
540 return(i);
541 }
542
543 asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
544 {
545 int i;
546
547 if (!suser())
548 return -EPERM;
549 if (gidsetsize > NGROUPS)
550 return -EINVAL;
551 for (i = 0; i < gidsetsize; i++, grouplist++) {
552 current->groups[i] = get_fs_word((unsigned short *) grouplist);
553 }
554 if (i < NGROUPS)
555 current->groups[i] = NOGROUP;
556 return 0;
557 }
558
559 int in_group_p(gid_t grp)
560 {
561 int i;
562
563 if (grp == current->egid)
564 return 1;
565
566 for (i = 0; i < NGROUPS; i++) {
567 if (current->groups[i] == NOGROUP)
568 break;
569 if (current->groups[i] == grp)
570 return 1;
571 }
572 return 0;
573 }
574
575 asmlinkage int sys_newuname(struct new_utsname * name)
576 {
577 int error;
578
579 if (!name)
580 return -EFAULT;
581 error = verify_area(VERIFY_WRITE, name, sizeof *name);
582 if (!error)
583 memcpy_tofs(name,&system_utsname,sizeof *name);
584 return error;
585 }
586
587 asmlinkage int sys_uname(struct old_utsname * name)
588 {
589 int error;
590 if (!name)
591 return -EFAULT;
592 error = verify_area(VERIFY_WRITE, name,sizeof *name);
593 if (error)
594 return error;
595 memcpy_tofs(&name->sysname,&system_utsname.sysname,
596 sizeof (system_utsname.sysname));
597 memcpy_tofs(&name->nodename,&system_utsname.nodename,
598 sizeof (system_utsname.nodename));
599 memcpy_tofs(&name->release,&system_utsname.release,
600 sizeof (system_utsname.release));
601 memcpy_tofs(&name->version,&system_utsname.version,
602 sizeof (system_utsname.version));
603 memcpy_tofs(&name->machine,&system_utsname.machine,
604 sizeof (system_utsname.machine));
605 return 0;
606 }
607
608 asmlinkage int sys_olduname(struct oldold_utsname * name)
609 {
610 int error;
611 if (!name)
612 return -EFAULT;
613 error = verify_area(VERIFY_WRITE, name,sizeof *name);
614 if (error)
615 return error;
616 memcpy_tofs(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
617 put_fs_byte(0,name->sysname+__OLD_UTS_LEN);
618 memcpy_tofs(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
619 put_fs_byte(0,name->nodename+__OLD_UTS_LEN);
620 memcpy_tofs(&name->release,&system_utsname.release,__OLD_UTS_LEN);
621 put_fs_byte(0,name->release+__OLD_UTS_LEN);
622 memcpy_tofs(&name->version,&system_utsname.version,__OLD_UTS_LEN);
623 put_fs_byte(0,name->version+__OLD_UTS_LEN);
624 memcpy_tofs(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
625 put_fs_byte(0,name->machine+__OLD_UTS_LEN);
626 return 0;
627 }
628
629
630
631
632 asmlinkage int sys_sethostname(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.nodename[i] = get_fs_byte(name+i)) == 0)
642 return 0;
643 }
644 system_utsname.nodename[i] = 0;
645 return 0;
646 }
647
648
649
650
651
652 asmlinkage int sys_setdomainname(char *name, int len)
653 {
654 int i;
655
656 if (!suser())
657 return -EPERM;
658 if (len > __NEW_UTS_LEN)
659 return -EINVAL;
660 for (i=0; i < len; i++) {
661 if ((system_utsname.domainname[i] = get_fs_byte(name+i)) == 0)
662 return 0;
663 }
664 system_utsname.domainname[i] = 0;
665 return 0;
666 }
667
668 asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
669 {
670 int error;
671
672 if (resource >= RLIM_NLIMITS)
673 return -EINVAL;
674 error = verify_area(VERIFY_WRITE,rlim,sizeof *rlim);
675 if (error)
676 return error;
677 put_fs_long(current->rlim[resource].rlim_cur,
678 (unsigned long *) rlim);
679 put_fs_long(current->rlim[resource].rlim_max,
680 ((unsigned long *) rlim)+1);
681 return 0;
682 }
683
684 asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
685 {
686 struct rlimit new_rlim, *old_rlim;
687
688 if (resource >= RLIM_NLIMITS)
689 return -EINVAL;
690 old_rlim = current->rlim + resource;
691 new_rlim.rlim_cur = get_fs_long((unsigned long *) rlim);
692 new_rlim.rlim_max = get_fs_long(((unsigned long *) rlim)+1);
693 if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
694 (new_rlim.rlim_max > old_rlim->rlim_max)) &&
695 !suser())
696 return -EPERM;
697 *old_rlim = new_rlim;
698 return 0;
699 }
700
701
702
703
704
705
706
707
708
709 int getrusage(struct task_struct *p, int who, struct rusage *ru)
710 {
711 int error;
712 struct rusage r;
713 unsigned long *lp, *lpend, *dest;
714
715 error = verify_area(VERIFY_WRITE, ru, sizeof *ru);
716 if (error)
717 return error;
718 memset((char *) &r, 0, sizeof(r));
719 switch (who) {
720 case RUSAGE_SELF:
721 r.ru_utime.tv_sec = CT_TO_SECS(p->utime);
722 r.ru_utime.tv_usec = CT_TO_USECS(p->utime);
723 r.ru_stime.tv_sec = CT_TO_SECS(p->stime);
724 r.ru_stime.tv_usec = CT_TO_USECS(p->stime);
725 r.ru_minflt = p->min_flt;
726 r.ru_majflt = p->maj_flt;
727 break;
728 case RUSAGE_CHILDREN:
729 r.ru_utime.tv_sec = CT_TO_SECS(p->cutime);
730 r.ru_utime.tv_usec = CT_TO_USECS(p->cutime);
731 r.ru_stime.tv_sec = CT_TO_SECS(p->cstime);
732 r.ru_stime.tv_usec = CT_TO_USECS(p->cstime);
733 r.ru_minflt = p->cmin_flt;
734 r.ru_majflt = p->cmaj_flt;
735 break;
736 default:
737 r.ru_utime.tv_sec = CT_TO_SECS(p->utime + p->cutime);
738 r.ru_utime.tv_usec = CT_TO_USECS(p->utime + p->cutime);
739 r.ru_stime.tv_sec = CT_TO_SECS(p->stime + p->cstime);
740 r.ru_stime.tv_usec = CT_TO_USECS(p->stime + p->cstime);
741 r.ru_minflt = p->min_flt + p->cmin_flt;
742 r.ru_majflt = p->maj_flt + p->cmaj_flt;
743 break;
744 }
745 lp = (unsigned long *) &r;
746 lpend = (unsigned long *) (&r+1);
747 dest = (unsigned long *) ru;
748 for (; lp < lpend; lp++, dest++)
749 put_fs_long(*lp, dest);
750 return 0;
751 }
752
753 asmlinkage int sys_getrusage(int who, struct rusage *ru)
754 {
755 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
756 return -EINVAL;
757 return getrusage(current, who, ru);
758 }
759
760 asmlinkage int sys_umask(int mask)
761 {
762 int old = current->umask;
763
764 current->umask = mask & S_IRWXUGO;
765 return (old);
766 }