This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / kernel / sys.c
1 /*
2  *  linux/kernel/sys.c
3  *
4  *  Copyright (C) 1991, 1992  Linus Torvalds
5  */
6
7 #include <linux/config.h>
8 #include <linux/compat.h>
9 #include <linux/module.h>
10 #include <linux/mm.h>
11 #include <linux/utsname.h>
12 #include <linux/mman.h>
13 #include <linux/smp_lock.h>
14 #include <linux/notifier.h>
15 #include <linux/kmod.h>
16 #include <linux/reboot.h>
17 #include <linux/prctl.h>
18 #include <linux/init.h>
19 #include <linux/highuid.h>
20 #include <linux/fs.h>
21 #include <linux/kernel.h>
22 #include <linux/kexec.h>
23 #include <linux/workqueue.h>
24 #include <linux/device.h>
25 #include <linux/times.h>
26 #include <linux/security.h>
27 #include <linux/dcookies.h>
28 #include <linux/suspend.h>
29 #include <linux/ckrm.h>
30 #include <linux/vs_base.h>
31 #include <linux/vs_cvirt.h>
32
33 #include <asm/uaccess.h>
34 #include <asm/io.h>
35 #include <asm/unistd.h>
36
37 #ifndef SET_UNALIGN_CTL
38 # define SET_UNALIGN_CTL(a,b)   (-EINVAL)
39 #endif
40 #ifndef GET_UNALIGN_CTL
41 # define GET_UNALIGN_CTL(a,b)   (-EINVAL)
42 #endif
43 #ifndef SET_FPEMU_CTL
44 # define SET_FPEMU_CTL(a,b)     (-EINVAL)
45 #endif
46 #ifndef GET_FPEMU_CTL
47 # define GET_FPEMU_CTL(a,b)     (-EINVAL)
48 #endif
49 #ifndef SET_FPEXC_CTL
50 # define SET_FPEXC_CTL(a,b)     (-EINVAL)
51 #endif
52 #ifndef GET_FPEXC_CTL
53 # define GET_FPEXC_CTL(a,b)     (-EINVAL)
54 #endif
55
56 /*
57  * this is where the system-wide overflow UID and GID are defined, for
58  * architectures that now have 32-bit UID/GID but didn't in the past
59  */
60
61 int overflowuid = DEFAULT_OVERFLOWUID;
62 int overflowgid = DEFAULT_OVERFLOWGID;
63
64 #ifdef CONFIG_UID16
65 EXPORT_SYMBOL(overflowuid);
66 EXPORT_SYMBOL(overflowgid);
67 #endif
68
69 /*
70  * the same as above, but for filesystems which can only store a 16-bit
71  * UID and GID. as such, this is needed on all architectures
72  */
73
74 int fs_overflowuid = DEFAULT_FS_OVERFLOWUID;
75 int fs_overflowgid = DEFAULT_FS_OVERFLOWUID;
76
77 EXPORT_SYMBOL(fs_overflowuid);
78 EXPORT_SYMBOL(fs_overflowgid);
79
80 /*
81  * this indicates whether you can reboot with ctrl-alt-del: the default is yes
82  */
83
84 int C_A_D = 1;
85 int cad_pid = 1;
86
87 /*
88  *      Notifier list for kernel code which wants to be called
89  *      at shutdown. This is used to stop any idling DMA operations
90  *      and the like. 
91  */
92
93 static struct notifier_block *reboot_notifier_list;
94 rwlock_t notifier_lock = RW_LOCK_UNLOCKED;
95
96 /**
97  *      notifier_chain_register - Add notifier to a notifier chain
98  *      @list: Pointer to root list pointer
99  *      @n: New entry in notifier chain
100  *
101  *      Adds a notifier to a notifier chain.
102  *
103  *      Currently always returns zero.
104  */
105  
106 int notifier_chain_register(struct notifier_block **list, struct notifier_block *n)
107 {
108         write_lock(&notifier_lock);
109         while(*list)
110         {
111                 if(n->priority > (*list)->priority)
112                         break;
113                 list= &((*list)->next);
114         }
115         n->next = *list;
116         *list=n;
117         write_unlock(&notifier_lock);
118         return 0;
119 }
120
121 EXPORT_SYMBOL(notifier_chain_register);
122
123 /**
124  *      notifier_chain_unregister - Remove notifier from a notifier chain
125  *      @nl: Pointer to root list pointer
126  *      @n: New entry in notifier chain
127  *
128  *      Removes a notifier from a notifier chain.
129  *
130  *      Returns zero on success, or %-ENOENT on failure.
131  */
132  
133 int notifier_chain_unregister(struct notifier_block **nl, struct notifier_block *n)
134 {
135         write_lock(&notifier_lock);
136         while((*nl)!=NULL)
137         {
138                 if((*nl)==n)
139                 {
140                         *nl=n->next;
141                         write_unlock(&notifier_lock);
142                         return 0;
143                 }
144                 nl=&((*nl)->next);
145         }
146         write_unlock(&notifier_lock);
147         return -ENOENT;
148 }
149
150 EXPORT_SYMBOL(notifier_chain_unregister);
151
152 /**
153  *      notifier_call_chain - Call functions in a notifier chain
154  *      @n: Pointer to root pointer of notifier chain
155  *      @val: Value passed unmodified to notifier function
156  *      @v: Pointer passed unmodified to notifier function
157  *
158  *      Calls each function in a notifier chain in turn.
159  *
160  *      If the return value of the notifier can be and'd
161  *      with %NOTIFY_STOP_MASK, then notifier_call_chain
162  *      will return immediately, with the return value of
163  *      the notifier function which halted execution.
164  *      Otherwise, the return value is the return value
165  *      of the last notifier function called.
166  */
167  
168 int notifier_call_chain(struct notifier_block **n, unsigned long val, void *v)
169 {
170         int ret=NOTIFY_DONE;
171         struct notifier_block *nb = *n;
172
173         while(nb)
174         {
175                 ret=nb->notifier_call(nb,val,v);
176                 if(ret&NOTIFY_STOP_MASK)
177                 {
178                         return ret;
179                 }
180                 nb=nb->next;
181         }
182         return ret;
183 }
184
185 EXPORT_SYMBOL(notifier_call_chain);
186
187 /**
188  *      register_reboot_notifier - Register function to be called at reboot time
189  *      @nb: Info about notifier function to be called
190  *
191  *      Registers a function with the list of functions
192  *      to be called at reboot time.
193  *
194  *      Currently always returns zero, as notifier_chain_register
195  *      always returns zero.
196  */
197  
198 int register_reboot_notifier(struct notifier_block * nb)
199 {
200         return notifier_chain_register(&reboot_notifier_list, nb);
201 }
202
203 EXPORT_SYMBOL(register_reboot_notifier);
204
205 /**
206  *      unregister_reboot_notifier - Unregister previously registered reboot notifier
207  *      @nb: Hook to be unregistered
208  *
209  *      Unregisters a previously registered reboot
210  *      notifier function.
211  *
212  *      Returns zero on success, or %-ENOENT on failure.
213  */
214  
215 int unregister_reboot_notifier(struct notifier_block * nb)
216 {
217         return notifier_chain_unregister(&reboot_notifier_list, nb);
218 }
219
220 EXPORT_SYMBOL(unregister_reboot_notifier);
221
222 asmlinkage long sys_ni_syscall(void)
223 {
224         return -ENOSYS;
225 }
226
227 cond_syscall(sys_nfsservctl)
228 cond_syscall(sys_quotactl)
229 cond_syscall(sys_acct)
230 cond_syscall(sys_lookup_dcookie)
231 cond_syscall(sys_swapon)
232 cond_syscall(sys_swapoff)
233 cond_syscall(sys_init_module)
234 cond_syscall(sys_delete_module)
235 cond_syscall(sys_socketpair)
236 cond_syscall(sys_bind)
237 cond_syscall(sys_listen)
238 cond_syscall(sys_accept)
239 cond_syscall(sys_connect)
240 cond_syscall(sys_getsockname)
241 cond_syscall(sys_getpeername)
242 cond_syscall(sys_sendto)
243 cond_syscall(sys_send)
244 cond_syscall(sys_recvfrom)
245 cond_syscall(sys_recv)
246 cond_syscall(sys_socket)
247 cond_syscall(sys_setsockopt)
248 cond_syscall(sys_getsockopt)
249 cond_syscall(sys_shutdown)
250 cond_syscall(sys_sendmsg)
251 cond_syscall(sys_recvmsg)
252 cond_syscall(sys_socketcall)
253 cond_syscall(sys_futex)
254 cond_syscall(compat_sys_futex)
255 cond_syscall(sys_epoll_create)
256 cond_syscall(sys_epoll_ctl)
257 cond_syscall(sys_epoll_wait)
258 cond_syscall(sys_semget)
259 cond_syscall(sys_semop)
260 cond_syscall(sys_semtimedop)
261 cond_syscall(sys_semctl)
262 cond_syscall(sys_msgget)
263 cond_syscall(sys_msgsnd)
264 cond_syscall(sys_msgrcv)
265 cond_syscall(sys_msgctl)
266 cond_syscall(sys_shmget)
267 cond_syscall(sys_shmdt)
268 cond_syscall(sys_shmctl)
269 cond_syscall(sys_mq_open)
270 cond_syscall(sys_mq_unlink)
271 cond_syscall(sys_mq_timedsend)
272 cond_syscall(sys_mq_timedreceive)
273 cond_syscall(sys_mq_notify)
274 cond_syscall(sys_mq_getsetattr)
275 cond_syscall(compat_sys_mq_open)
276 cond_syscall(compat_sys_mq_timedsend)
277 cond_syscall(compat_sys_mq_timedreceive)
278 cond_syscall(compat_sys_mq_notify)
279 cond_syscall(compat_sys_mq_getsetattr)
280 cond_syscall(sys_mbind)
281 cond_syscall(sys_get_mempolicy)
282 cond_syscall(sys_set_mempolicy)
283 cond_syscall(compat_get_mempolicy)
284
285 /* arch-specific weak syscall entries */
286 cond_syscall(sys_pciconfig_read)
287 cond_syscall(sys_pciconfig_write)
288 cond_syscall(sys_pciconfig_iobase)
289
290 static int set_one_prio(struct task_struct *p, int niceval, int error)
291 {
292         int no_nice;
293
294         if (p->uid != current->euid &&
295                 p->uid != current->uid && !capable(CAP_SYS_NICE)) {
296                 error = -EPERM;
297                 goto out;
298         }
299         if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) {
300                 error = -EACCES;
301                 goto out;
302         }
303         no_nice = security_task_setnice(p, niceval);
304         if (no_nice) {
305                 error = no_nice;
306                 goto out;
307         }
308         if (error == -ESRCH)
309                 error = 0;
310         set_user_nice(p, niceval);
311 out:
312         return error;
313 }
314
315 asmlinkage long sys_setpriority(int which, int who, int niceval)
316 {
317         struct task_struct *g, *p;
318         struct user_struct *user;
319         struct pid *pid;
320         struct list_head *l;
321         int error = -EINVAL;
322
323         if (which > 2 || which < 0)
324                 goto out;
325
326         /* normalize: avoid signed division (rounding problems) */
327         error = -ESRCH;
328         if (niceval < -20)
329                 niceval = -20;
330         if (niceval > 19)
331                 niceval = 19;
332
333         read_lock(&tasklist_lock);
334         switch (which) {
335                 case PRIO_PROCESS:
336                         if (!who)
337                                 who = current->pid;
338                         p = find_task_by_pid(who);
339                         if (p)
340                                 error = set_one_prio(p, niceval, error);
341                         break;
342                 case PRIO_PGRP:
343                         if (!who)
344                                 who = process_group(current);
345                         for_each_task_pid(who, PIDTYPE_PGID, p, l, pid)
346                                 error = set_one_prio(p, niceval, error);
347                         break;
348                 case PRIO_USER:
349                         if (!who)
350                                 user = current->user;
351                         else
352                                 user = find_user(vx_current_xid(), who);
353
354                         if (!user)
355                                 goto out_unlock;
356
357                         do_each_thread(g, p)
358                                 if (p->uid == who)
359                                         error = set_one_prio(p, niceval, error);
360                         while_each_thread(g, p);
361                         if (who)
362                                 free_uid(user);         /* For find_user() */
363                         break;
364         }
365 out_unlock:
366         read_unlock(&tasklist_lock);
367 out:
368         return error;
369 }
370
371 /*
372  * Ugh. To avoid negative return values, "getpriority()" will
373  * not return the normal nice-value, but a negated value that
374  * has been offset by 20 (ie it returns 40..1 instead of -20..19)
375  * to stay compatible.
376  */
377 asmlinkage long sys_getpriority(int which, int who)
378 {
379         struct task_struct *g, *p;
380         struct list_head *l;
381         struct pid *pid;
382         struct user_struct *user;
383         long niceval, retval = -ESRCH;
384
385         if (which > 2 || which < 0)
386                 return -EINVAL;
387
388         read_lock(&tasklist_lock);
389         switch (which) {
390                 case PRIO_PROCESS:
391                         if (!who)
392                                 who = current->pid;
393                         p = find_task_by_pid(who);
394                         if (p) {
395                                 niceval = 20 - task_nice(p);
396                                 if (niceval > retval)
397                                         retval = niceval;
398                         }
399                         break;
400                 case PRIO_PGRP:
401                         if (!who)
402                                 who = process_group(current);
403                         for_each_task_pid(who, PIDTYPE_PGID, p, l, pid) {
404                                 niceval = 20 - task_nice(p);
405                                 if (niceval > retval)
406                                         retval = niceval;
407                         }
408                         break;
409                 case PRIO_USER:
410                         if (!who)
411                                 user = current->user;
412                         else
413                                 user = find_user(vx_current_xid(), who);
414
415                         if (!user)
416                                 goto out_unlock;
417
418                         do_each_thread(g, p)
419                                 if (p->uid == who) {
420                                         niceval = 20 - task_nice(p);
421                                         if (niceval > retval)
422                                                 retval = niceval;
423                                 }
424                         while_each_thread(g, p);
425                         if (who)
426                                 free_uid(user);         /* for find_user() */
427                         break;
428         }
429 out_unlock:
430         read_unlock(&tasklist_lock);
431
432         return retval;
433 }
434
435 long vs_reboot(unsigned int, void *);
436
437 /*
438  * Reboot system call: for obvious reasons only root may call it,
439  * and even root needs to set up some magic numbers in the registers
440  * so that some mistake won't make this reboot the whole machine.
441  * You can also set the meaning of the ctrl-alt-del-key here.
442  *
443  * reboot doesn't sync: do that yourself before calling this.
444  */
445 asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void __user * arg)
446 {
447         char buffer[256];
448
449         /* We only trust the superuser with rebooting the system. */
450         if (!capable(CAP_SYS_BOOT))
451                 return -EPERM;
452
453         /* For safety, we require "magic" arguments. */
454         if (magic1 != LINUX_REBOOT_MAGIC1 ||
455             (magic2 != LINUX_REBOOT_MAGIC2 &&
456                         magic2 != LINUX_REBOOT_MAGIC2A &&
457                         magic2 != LINUX_REBOOT_MAGIC2B &&
458                         magic2 != LINUX_REBOOT_MAGIC2C))
459                 return -EINVAL;
460
461         if (!vx_check(0, VX_ADMIN|VX_WATCH))
462                 return vs_reboot(cmd, arg);
463
464         lock_kernel();
465         switch (cmd) {
466         case LINUX_REBOOT_CMD_RESTART:
467                 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
468                 system_state = SYSTEM_RESTART;
469                 device_shutdown();
470                 printk(KERN_EMERG "Restarting system.\n");
471                 machine_restart(NULL);
472                 break;
473
474         case LINUX_REBOOT_CMD_CAD_ON:
475                 C_A_D = 1;
476                 break;
477
478         case LINUX_REBOOT_CMD_CAD_OFF:
479                 C_A_D = 0;
480                 break;
481
482         case LINUX_REBOOT_CMD_HALT:
483                 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL);
484                 system_state = SYSTEM_HALT;
485                 device_shutdown();
486                 printk(KERN_EMERG "System halted.\n");
487                 machine_halt();
488                 unlock_kernel();
489                 do_exit(0);
490                 break;
491
492         case LINUX_REBOOT_CMD_POWER_OFF:
493                 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL);
494                 system_state = SYSTEM_POWER_OFF;
495                 device_shutdown();
496                 printk(KERN_EMERG "Power down.\n");
497                 machine_power_off();
498                 unlock_kernel();
499                 do_exit(0);
500                 break;
501
502         case LINUX_REBOOT_CMD_RESTART2:
503                 if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {
504                         unlock_kernel();
505                         return -EFAULT;
506                 }
507                 buffer[sizeof(buffer) - 1] = '\0';
508
509                 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer);
510                 system_state = SYSTEM_RESTART;
511                 device_shutdown();
512                 printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer);
513                 machine_restart(buffer);
514                 break;
515
516 #ifdef CONFIG_KEXEC
517         case LINUX_REBOOT_CMD_KEXEC:
518         {
519                 struct kimage *image;
520                 image = xchg(&kexec_image, 0);
521                 if (!image) {
522                         unlock_kernel();
523                         return -EINVAL;
524                 }
525                 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
526                 system_state = SYSTEM_RESTART;
527                 device_shutdown();
528                 system_state = SYSTEM_BOOTING;
529                 printk(KERN_EMERG "Starting new kernel\n");
530                 machine_shutdown();
531                 machine_kexec(image);
532                 break;
533         }
534 #endif
535 #ifdef CONFIG_SOFTWARE_SUSPEND
536         case LINUX_REBOOT_CMD_SW_SUSPEND:
537                 {
538                         int ret = software_suspend();
539                         unlock_kernel();
540                         return ret;
541                 }
542 #endif
543
544         default:
545                 unlock_kernel();
546                 return -EINVAL;
547         }
548         unlock_kernel();
549         return 0;
550 }
551
552 static void deferred_cad(void *dummy)
553 {
554         notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
555         machine_restart(NULL);
556 }
557
558 /*
559  * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
560  * As it's called within an interrupt, it may NOT sync: the only choice
561  * is whether to reboot at once, or just ignore the ctrl-alt-del.
562  */
563 void ctrl_alt_del(void)
564 {
565         static DECLARE_WORK(cad_work, deferred_cad, NULL);
566
567         if (C_A_D)
568                 schedule_work(&cad_work);
569         else
570                 kill_proc(cad_pid, SIGINT, 1);
571 }
572         
573
574 /*
575  * Unprivileged users may change the real gid to the effective gid
576  * or vice versa.  (BSD-style)
577  *
578  * If you set the real gid at all, or set the effective gid to a value not
579  * equal to the real gid, then the saved gid is set to the new effective gid.
580  *
581  * This makes it possible for a setgid program to completely drop its
582  * privileges, which is often a useful assertion to make when you are doing
583  * a security audit over a program.
584  *
585  * The general idea is that a program which uses just setregid() will be
586  * 100% compatible with BSD.  A program which uses just setgid() will be
587  * 100% compatible with POSIX with saved IDs. 
588  *
589  * SMP: There are not races, the GIDs are checked only by filesystem
590  *      operations (as far as semantic preservation is concerned).
591  */
592 asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
593 {
594         int old_rgid = current->gid;
595         int old_egid = current->egid;
596         int new_rgid = old_rgid;
597         int new_egid = old_egid;
598         int retval;
599
600         retval = security_task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
601         if (retval)
602                 return retval;
603
604         if (rgid != (gid_t) -1) {
605                 if ((old_rgid == rgid) ||
606                     (current->egid==rgid) ||
607                     capable(CAP_SETGID))
608                         new_rgid = rgid;
609                 else
610                         return -EPERM;
611         }
612         if (egid != (gid_t) -1) {
613                 if ((old_rgid == egid) ||
614                     (current->egid == egid) ||
615                     (current->sgid == egid) ||
616                     capable(CAP_SETGID))
617                         new_egid = egid;
618                 else {
619                         return -EPERM;
620                 }
621         }
622         if (new_egid != old_egid)
623         {
624                 current->mm->dumpable = 0;
625                 wmb();
626         }
627         if (rgid != (gid_t) -1 ||
628             (egid != (gid_t) -1 && egid != old_rgid))
629                 current->sgid = new_egid;
630         current->fsgid = new_egid;
631         current->egid = new_egid;
632         current->gid = new_rgid;
633
634         ckrm_cb_gid();
635
636         return 0;
637 }
638
639 /*
640  * setgid() is implemented like SysV w/ SAVED_IDS 
641  *
642  * SMP: Same implicit races as above.
643  */
644 asmlinkage long sys_setgid(gid_t gid)
645 {
646         int old_egid = current->egid;
647         int retval;
648
649         retval = security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
650         if (retval)
651                 return retval;
652
653         if (capable(CAP_SETGID))
654         {
655                 if(old_egid != gid)
656                 {
657                         current->mm->dumpable=0;
658                         wmb();
659                 }
660                 current->gid = current->egid = current->sgid = current->fsgid = gid;
661         }
662         else if ((gid == current->gid) || (gid == current->sgid))
663         {
664                 if(old_egid != gid)
665                 {
666                         current->mm->dumpable=0;
667                         wmb();
668                 }
669                 current->egid = current->fsgid = gid;
670         }
671         else
672                 return -EPERM;
673
674         ckrm_cb_gid();
675
676         return 0;
677 }
678   
679 static int set_user(uid_t new_ruid, int dumpclear)
680 {
681         struct user_struct *new_user;
682
683         new_user = alloc_uid(vx_current_xid(), new_ruid);
684         if (!new_user)
685                 return -EAGAIN;
686
687         if (atomic_read(&new_user->processes) >=
688                                 current->rlim[RLIMIT_NPROC].rlim_cur &&
689                         new_user != &root_user) {
690                 free_uid(new_user);
691                 return -EAGAIN;
692         }
693
694         switch_uid(new_user);
695
696         if(dumpclear)
697         {
698                 current->mm->dumpable = 0;
699                 wmb();
700         }
701         current->uid = new_ruid;
702         return 0;
703 }
704
705 /*
706  * Unprivileged users may change the real uid to the effective uid
707  * or vice versa.  (BSD-style)
708  *
709  * If you set the real uid at all, or set the effective uid to a value not
710  * equal to the real uid, then the saved uid is set to the new effective uid.
711  *
712  * This makes it possible for a setuid program to completely drop its
713  * privileges, which is often a useful assertion to make when you are doing
714  * a security audit over a program.
715  *
716  * The general idea is that a program which uses just setreuid() will be
717  * 100% compatible with BSD.  A program which uses just setuid() will be
718  * 100% compatible with POSIX with saved IDs. 
719  */
720 asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
721 {
722         int old_ruid, old_euid, old_suid, new_ruid, new_euid;
723         int retval;
724
725         retval = security_task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
726         if (retval)
727                 return retval;
728
729         new_ruid = old_ruid = current->uid;
730         new_euid = old_euid = current->euid;
731         old_suid = current->suid;
732
733         if (ruid != (uid_t) -1) {
734                 new_ruid = ruid;
735                 if ((old_ruid != ruid) &&
736                     (current->euid != ruid) &&
737                     !capable(CAP_SETUID))
738                         return -EPERM;
739         }
740
741         if (euid != (uid_t) -1) {
742                 new_euid = euid;
743                 if ((old_ruid != euid) &&
744                     (current->euid != euid) &&
745                     (current->suid != euid) &&
746                     !capable(CAP_SETUID))
747                         return -EPERM;
748         }
749
750         if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)
751                 return -EAGAIN;
752
753         if (new_euid != old_euid)
754         {
755                 current->mm->dumpable=0;
756                 wmb();
757         }
758         current->fsuid = current->euid = new_euid;
759         if (ruid != (uid_t) -1 ||
760             (euid != (uid_t) -1 && euid != old_ruid))
761                 current->suid = current->euid;
762         current->fsuid = current->euid;
763
764         ckrm_cb_uid();
765
766         return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
767 }
768
769
770                 
771 /*
772  * setuid() is implemented like SysV with SAVED_IDS 
773  * 
774  * Note that SAVED_ID's is deficient in that a setuid root program
775  * like sendmail, for example, cannot set its uid to be a normal 
776  * user and then switch back, because if you're root, setuid() sets
777  * the saved uid too.  If you don't like this, blame the bright people
778  * in the POSIX committee and/or USG.  Note that the BSD-style setreuid()
779  * will allow a root program to temporarily drop privileges and be able to
780  * regain them by swapping the real and effective uid.  
781  */
782 asmlinkage long sys_setuid(uid_t uid)
783 {
784         int old_euid = current->euid;
785         int old_ruid, old_suid, new_ruid, new_suid;
786         int retval;
787
788         retval = security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
789         if (retval)
790                 return retval;
791
792         old_ruid = new_ruid = current->uid;
793         old_suid = current->suid;
794         new_suid = old_suid;
795         
796         if (capable(CAP_SETUID)) {
797                 if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
798                         return -EAGAIN;
799                 new_suid = uid;
800         } else if ((uid != current->uid) && (uid != new_suid))
801                 return -EPERM;
802
803         if (old_euid != uid)
804         {
805                 current->mm->dumpable = 0;
806                 wmb();
807         }
808         current->fsuid = current->euid = uid;
809         current->suid = new_suid;
810
811         ckrm_cb_uid();
812
813         return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
814 }
815
816
817 /*
818  * This function implements a generic ability to update ruid, euid,
819  * and suid.  This allows you to implement the 4.4 compatible seteuid().
820  */
821 asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
822 {
823         int old_ruid = current->uid;
824         int old_euid = current->euid;
825         int old_suid = current->suid;
826         int retval;
827
828         retval = security_task_setuid(ruid, euid, suid, LSM_SETID_RES);
829         if (retval)
830                 return retval;
831
832         if (!capable(CAP_SETUID)) {
833                 if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
834                     (ruid != current->euid) && (ruid != current->suid))
835                         return -EPERM;
836                 if ((euid != (uid_t) -1) && (euid != current->uid) &&
837                     (euid != current->euid) && (euid != current->suid))
838                         return -EPERM;
839                 if ((suid != (uid_t) -1) && (suid != current->uid) &&
840                     (suid != current->euid) && (suid != current->suid))
841                         return -EPERM;
842         }
843         if (ruid != (uid_t) -1) {
844                 if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)
845                         return -EAGAIN;
846         }
847         if (euid != (uid_t) -1) {
848                 if (euid != current->euid)
849                 {
850                         current->mm->dumpable = 0;
851                         wmb();
852                 }
853                 current->euid = euid;
854         }
855         current->fsuid = current->euid;
856         if (suid != (uid_t) -1)
857                 current->suid = suid;
858
859         ckrm_cb_uid();
860
861         return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
862 }
863
864 asmlinkage long sys_getresuid(uid_t __user *ruid, uid_t __user *euid, uid_t __user *suid)
865 {
866         int retval;
867
868         if (!(retval = put_user(current->uid, ruid)) &&
869             !(retval = put_user(current->euid, euid)))
870                 retval = put_user(current->suid, suid);
871
872         return retval;
873 }
874
875 /*
876  * Same as above, but for rgid, egid, sgid.
877  */
878 asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
879 {
880         int retval;
881
882         retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
883         if (retval)
884                 return retval;
885
886         if (!capable(CAP_SETGID)) {
887                 if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
888                     (rgid != current->egid) && (rgid != current->sgid))
889                         return -EPERM;
890                 if ((egid != (gid_t) -1) && (egid != current->gid) &&
891                     (egid != current->egid) && (egid != current->sgid))
892                         return -EPERM;
893                 if ((sgid != (gid_t) -1) && (sgid != current->gid) &&
894                     (sgid != current->egid) && (sgid != current->sgid))
895                         return -EPERM;
896         }
897         if (egid != (gid_t) -1) {
898                 if (egid != current->egid)
899                 {
900                         current->mm->dumpable = 0;
901                         wmb();
902                 }
903                 current->egid = egid;
904         }
905         current->fsgid = current->egid;
906         if (rgid != (gid_t) -1)
907                 current->gid = rgid;
908         if (sgid != (gid_t) -1)
909                 current->sgid = sgid;
910
911         ckrm_cb_gid();
912
913         return 0;
914 }
915
916 asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid)
917 {
918         int retval;
919
920         if (!(retval = put_user(current->gid, rgid)) &&
921             !(retval = put_user(current->egid, egid)))
922                 retval = put_user(current->sgid, sgid);
923
924         return retval;
925 }
926
927
928 /*
929  * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This
930  * is used for "access()" and for the NFS daemon (letting nfsd stay at
931  * whatever uid it wants to). It normally shadows "euid", except when
932  * explicitly set by setfsuid() or for access..
933  */
934 asmlinkage long sys_setfsuid(uid_t uid)
935 {
936         int old_fsuid;
937
938         old_fsuid = current->fsuid;
939         if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS))
940                 return old_fsuid;
941
942         if (uid == current->uid || uid == current->euid ||
943             uid == current->suid || uid == current->fsuid || 
944             capable(CAP_SETUID))
945         {
946                 if (uid != old_fsuid)
947                 {
948                         current->mm->dumpable = 0;
949                         wmb();
950                 }
951                 current->fsuid = uid;
952         }
953
954         security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
955
956         return old_fsuid;
957 }
958
959 /*
960  * Samma pÃ¥ svenska..
961  */
962 asmlinkage long sys_setfsgid(gid_t gid)
963 {
964         int old_fsgid;
965
966         old_fsgid = current->fsgid;
967         if (security_task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS))
968                 return old_fsgid;
969
970         if (gid == current->gid || gid == current->egid ||
971             gid == current->sgid || gid == current->fsgid || 
972             capable(CAP_SETGID))
973         {
974                 if (gid != old_fsgid)
975                 {
976                         current->mm->dumpable = 0;
977                         wmb();
978                 }
979                 current->fsgid = gid;
980         }
981         return old_fsgid;
982 }
983
984 asmlinkage long sys_times(struct tms __user * tbuf)
985 {
986         /*
987          *      In the SMP world we might just be unlucky and have one of
988          *      the times increment as we use it. Since the value is an
989          *      atomically safe type this is just fine. Conceptually its
990          *      as if the syscall took an instant longer to occur.
991          */
992         if (tbuf) {
993                 struct tms tmp;
994                 tmp.tms_utime = jiffies_to_clock_t(current->utime);
995                 tmp.tms_stime = jiffies_to_clock_t(current->stime);
996                 tmp.tms_cutime = jiffies_to_clock_t(current->cutime);
997                 tmp.tms_cstime = jiffies_to_clock_t(current->cstime);
998                 if (copy_to_user(tbuf, &tmp, sizeof(struct tms)))
999                         return -EFAULT;
1000         }
1001         return (long) jiffies_64_to_clock_t(get_jiffies_64());
1002 }
1003
1004 /*
1005  * This needs some heavy checking ...
1006  * I just haven't the stomach for it. I also don't fully
1007  * understand sessions/pgrp etc. Let somebody who does explain it.
1008  *
1009  * OK, I think I have the protection semantics right.... this is really
1010  * only important on a multi-user system anyway, to make sure one user
1011  * can't send a signal to a process owned by another.  -TYT, 12/12/91
1012  *
1013  * Auch. Had to add the 'did_exec' flag to conform completely to POSIX.
1014  * LBT 04.03.94
1015  */
1016
1017 asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
1018 {
1019         struct task_struct *p;
1020         int err = -EINVAL;
1021
1022         if (!pid)
1023                 pid = current->pid;
1024         if (!pgid)
1025                 pgid = pid;
1026         if (pgid < 0)
1027                 return -EINVAL;
1028
1029         /* From this point forward we keep holding onto the tasklist lock
1030          * so that our parent does not change from under us. -DaveM
1031          */
1032         write_lock_irq(&tasklist_lock);
1033
1034         err = -ESRCH;
1035         p = find_task_by_pid(pid);
1036         if (!p)
1037                 goto out;
1038
1039         err = -EINVAL;
1040         if (!thread_group_leader(p))
1041                 goto out;
1042
1043         if (p->parent == current || p->real_parent == current) {
1044                 err = -EPERM;
1045                 if (p->signal->session != current->signal->session)
1046                         goto out;
1047                 err = -EACCES;
1048                 if (p->did_exec)
1049                         goto out;
1050         } else {
1051                 err = -ESRCH;
1052                 if (p != current)
1053                         goto out;
1054         }
1055
1056         err = -EPERM;
1057         if (p->signal->leader)
1058                 goto out;
1059
1060         if (pgid != pid) {
1061                 struct task_struct *p;
1062                 struct pid *pid;
1063                 struct list_head *l;
1064
1065                 for_each_task_pid(pgid, PIDTYPE_PGID, p, l, pid)
1066                         if (p->signal->session == current->signal->session)
1067                                 goto ok_pgid;
1068                 goto out;
1069         }
1070
1071 ok_pgid:
1072         err = security_task_setpgid(p, pgid);
1073         if (err)
1074                 goto out;
1075
1076         if (process_group(p) != pgid) {
1077                 detach_pid(p, PIDTYPE_PGID);
1078                 p->signal->pgrp = pgid;
1079                 attach_pid(p, PIDTYPE_PGID, pgid);
1080         }
1081
1082         err = 0;
1083 out:
1084         /* All paths lead to here, thus we are safe. -DaveM */
1085         write_unlock_irq(&tasklist_lock);
1086         return err;
1087 }
1088
1089 asmlinkage long sys_getpgid(pid_t pid)
1090 {
1091         if (!pid) {
1092                 return process_group(current);
1093         } else {
1094                 int retval;
1095                 struct task_struct *p;
1096
1097                 read_lock(&tasklist_lock);
1098                 p = find_task_by_pid(pid);
1099
1100                 retval = -ESRCH;
1101                 if (p) {
1102                         retval = security_task_getpgid(p);
1103                         if (!retval)
1104                                 retval = process_group(p);
1105                 }
1106                 read_unlock(&tasklist_lock);
1107                 return retval;
1108         }
1109 }
1110
1111 #ifdef __ARCH_WANT_SYS_GETPGRP
1112
1113 asmlinkage long sys_getpgrp(void)
1114 {
1115         /* SMP - assuming writes are word atomic this is fine */
1116         return process_group(current);
1117 }
1118
1119 #endif
1120
1121 asmlinkage long sys_getsid(pid_t pid)
1122 {
1123         if (!pid) {
1124                 return current->signal->session;
1125         } else {
1126                 int retval;
1127                 struct task_struct *p;
1128
1129                 read_lock(&tasklist_lock);
1130                 p = find_task_by_pid(pid);
1131
1132                 retval = -ESRCH;
1133                 if(p) {
1134                         retval = security_task_getsid(p);
1135                         if (!retval)
1136                                 retval = p->signal->session;
1137                 }
1138                 read_unlock(&tasklist_lock);
1139                 return retval;
1140         }
1141 }
1142
1143 asmlinkage long sys_setsid(void)
1144 {
1145         struct pid *pid;
1146         int err = -EPERM;
1147
1148         if (!thread_group_leader(current))
1149                 return -EINVAL;
1150
1151         write_lock_irq(&tasklist_lock);
1152
1153         pid = find_pid(PIDTYPE_PGID, current->pid);
1154         if (pid)
1155                 goto out;
1156
1157         current->signal->leader = 1;
1158         __set_special_pids(current->pid, current->pid);
1159         current->signal->tty = NULL;
1160         current->signal->tty_old_pgrp = 0;
1161         err = process_group(current);
1162 out:
1163         write_unlock_irq(&tasklist_lock);
1164         return err;
1165 }
1166
1167 /*
1168  * Supplementary group IDs
1169  */
1170
1171 /* init to 2 - one for init_task, one to ensure it is never freed */
1172 struct group_info init_groups = { .usage = ATOMIC_INIT(2) };
1173
1174 struct group_info *groups_alloc(int gidsetsize)
1175 {
1176         struct group_info *group_info;
1177         int nblocks;
1178         int i;
1179
1180         nblocks = (gidsetsize + NGROUPS_PER_BLOCK - 1) / NGROUPS_PER_BLOCK;
1181         /* Make sure we always allocate at least one indirect block pointer */
1182         nblocks = nblocks ? : 1;
1183         group_info = kmalloc(sizeof(*group_info) + nblocks*sizeof(gid_t *), GFP_USER);
1184         if (!group_info)
1185                 return NULL;
1186         group_info->ngroups = gidsetsize;
1187         group_info->nblocks = nblocks;
1188         atomic_set(&group_info->usage, 1);
1189
1190         if (gidsetsize <= NGROUPS_SMALL) {
1191                 group_info->blocks[0] = group_info->small_block;
1192         } else {
1193                 for (i = 0; i < nblocks; i++) {
1194                         gid_t *b;
1195                         b = (void *)__get_free_page(GFP_USER);
1196                         if (!b)
1197                                 goto out_undo_partial_alloc;
1198                         group_info->blocks[i] = b;
1199                 }
1200         }
1201         return group_info;
1202
1203 out_undo_partial_alloc:
1204         while (--i >= 0) {
1205                 free_page((unsigned long)group_info->blocks[i]);
1206         }
1207         kfree(group_info);
1208         return NULL;
1209 }
1210
1211 EXPORT_SYMBOL(groups_alloc);
1212
1213 void groups_free(struct group_info *group_info)
1214 {
1215         if (group_info->blocks[0] != group_info->small_block) {
1216                 int i;
1217                 for (i = 0; i < group_info->nblocks; i++)
1218                         free_page((unsigned long)group_info->blocks[i]);
1219         }
1220         kfree(group_info);
1221 }
1222
1223 EXPORT_SYMBOL(groups_free);
1224
1225 /* export the group_info to a user-space array */
1226 static int groups_to_user(gid_t __user *grouplist,
1227     struct group_info *group_info)
1228 {
1229         int i;
1230         int count = group_info->ngroups;
1231
1232         for (i = 0; i < group_info->nblocks; i++) {
1233                 int cp_count = min(NGROUPS_PER_BLOCK, count);
1234                 int off = i * NGROUPS_PER_BLOCK;
1235                 int len = cp_count * sizeof(*grouplist);
1236
1237                 if (copy_to_user(grouplist+off, group_info->blocks[i], len))
1238                         return -EFAULT;
1239
1240                 count -= cp_count;
1241         }
1242         return 0;
1243 }
1244
1245 /* fill a group_info from a user-space array - it must be allocated already */
1246 static int groups_from_user(struct group_info *group_info,
1247     gid_t __user *grouplist)
1248  {
1249         int i;
1250         int count = group_info->ngroups;
1251
1252         for (i = 0; i < group_info->nblocks; i++) {
1253                 int cp_count = min(NGROUPS_PER_BLOCK, count);
1254                 int off = i * NGROUPS_PER_BLOCK;
1255                 int len = cp_count * sizeof(*grouplist);
1256
1257                 if (copy_from_user(group_info->blocks[i], grouplist+off, len))
1258                         return -EFAULT;
1259
1260                 count -= cp_count;
1261         }
1262         return 0;
1263 }
1264
1265 /* a simple shell-metzner sort */
1266 static void groups_sort(struct group_info *group_info)
1267 {
1268         int base, max, stride;
1269         int gidsetsize = group_info->ngroups;
1270
1271         for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
1272                 ; /* nothing */
1273         stride /= 3;
1274
1275         while (stride) {
1276                 max = gidsetsize - stride;
1277                 for (base = 0; base < max; base++) {
1278                         int left = base;
1279                         int right = left + stride;
1280                         gid_t tmp = GROUP_AT(group_info, right);
1281
1282                         while (left >= 0 && GROUP_AT(group_info, left) > tmp) {
1283                                 GROUP_AT(group_info, right) =
1284                                     GROUP_AT(group_info, left);
1285                                 right = left;
1286                                 left -= stride;
1287                         }
1288                         GROUP_AT(group_info, right) = tmp;
1289                 }
1290                 stride /= 3;
1291         }
1292 }
1293
1294 /* a simple bsearch */
1295 static int groups_search(struct group_info *group_info, gid_t grp)
1296 {
1297         int left, right;
1298
1299         if (!group_info)
1300                 return 0;
1301
1302         left = 0;
1303         right = group_info->ngroups;
1304         while (left < right) {
1305                 int mid = (left+right)/2;
1306                 int cmp = grp - GROUP_AT(group_info, mid);
1307                 if (cmp > 0)
1308                         left = mid + 1;
1309                 else if (cmp < 0)
1310                         right = mid;
1311                 else
1312                         return 1;
1313         }
1314         return 0;
1315 }
1316
1317 /* validate and set current->group_info */
1318 int set_current_groups(struct group_info *group_info)
1319 {
1320         int retval;
1321         struct group_info *old_info;
1322
1323         retval = security_task_setgroups(group_info);
1324         if (retval)
1325                 return retval;
1326
1327         groups_sort(group_info);
1328         get_group_info(group_info);
1329
1330         task_lock(current);
1331         old_info = current->group_info;
1332         current->group_info = group_info;
1333         task_unlock(current);
1334
1335         put_group_info(old_info);
1336
1337         return 0;
1338 }
1339
1340 EXPORT_SYMBOL(set_current_groups);
1341
1342 asmlinkage long sys_getgroups(int gidsetsize, gid_t __user *grouplist)
1343 {
1344         int i = 0;
1345
1346         /*
1347          *      SMP: Nobody else can change our grouplist. Thus we are
1348          *      safe.
1349          */
1350
1351         if (gidsetsize < 0)
1352                 return -EINVAL;
1353
1354         /* no need to grab task_lock here; it cannot change */
1355         get_group_info(current->group_info);
1356         i = current->group_info->ngroups;
1357         if (gidsetsize) {
1358                 if (i > gidsetsize) {
1359                         i = -EINVAL;
1360                         goto out;
1361                 }
1362                 if (groups_to_user(grouplist, current->group_info)) {
1363                         i = -EFAULT;
1364                         goto out;
1365                 }
1366         }
1367 out:
1368         put_group_info(current->group_info);
1369         return i;
1370 }
1371
1372 /*
1373  *      SMP: Our groups are copy-on-write. We can set them safely
1374  *      without another task interfering.
1375  */
1376  
1377 asmlinkage long sys_setgroups(int gidsetsize, gid_t __user *grouplist)
1378 {
1379         struct group_info *group_info;
1380         int retval;
1381
1382         if (!capable(CAP_SETGID))
1383                 return -EPERM;
1384         if ((unsigned)gidsetsize > NGROUPS_MAX)
1385                 return -EINVAL;
1386
1387         group_info = groups_alloc(gidsetsize);
1388         if (!group_info)
1389                 return -ENOMEM;
1390         retval = groups_from_user(group_info, grouplist);
1391         if (retval) {
1392                 put_group_info(group_info);
1393                 return retval;
1394         }
1395
1396         retval = set_current_groups(group_info);
1397         put_group_info(group_info);
1398
1399         return retval;
1400 }
1401
1402 /*
1403  * Check whether we're fsgid/egid or in the supplemental group..
1404  */
1405 int in_group_p(gid_t grp)
1406 {
1407         int retval = 1;
1408         if (grp != current->fsgid) {
1409                 get_group_info(current->group_info);
1410                 retval = groups_search(current->group_info, grp);
1411                 put_group_info(current->group_info);
1412         }
1413         return retval;
1414 }
1415
1416 EXPORT_SYMBOL(in_group_p);
1417
1418 int in_egroup_p(gid_t grp)
1419 {
1420         int retval = 1;
1421         if (grp != current->egid) {
1422                 get_group_info(current->group_info);
1423                 retval = groups_search(current->group_info, grp);
1424                 put_group_info(current->group_info);
1425         }
1426         return retval;
1427 }
1428
1429 EXPORT_SYMBOL(in_egroup_p);
1430
1431 DECLARE_RWSEM(uts_sem);
1432
1433 EXPORT_SYMBOL(uts_sem);
1434
1435 asmlinkage long sys_newuname(struct new_utsname __user * name)
1436 {
1437         int errno = 0;
1438
1439         down_read(&uts_sem);
1440         if (copy_to_user(name, vx_new_utsname(), sizeof *name))
1441                 errno = -EFAULT;
1442         up_read(&uts_sem);
1443         return errno;
1444 }
1445
1446 asmlinkage long sys_sethostname(char __user *name, int len)
1447 {
1448         int errno;
1449         char tmp[__NEW_UTS_LEN];
1450
1451         if (!capable(CAP_SYS_ADMIN) && !vx_ccaps(VXC_SET_UTSNAME))
1452                 return -EPERM;
1453         if (len < 0 || len > __NEW_UTS_LEN)
1454                 return -EINVAL;
1455         down_write(&uts_sem);
1456         errno = -EFAULT;
1457         if (!copy_from_user(tmp, name, len)) {
1458                 char *ptr = vx_new_uts(nodename);
1459
1460                 memcpy(ptr, tmp, len);
1461                 ptr[len] = 0;
1462                 errno = 0;
1463         }
1464         up_write(&uts_sem);
1465         return errno;
1466 }
1467
1468 #ifdef __ARCH_WANT_SYS_GETHOSTNAME
1469
1470 asmlinkage long sys_gethostname(char __user *name, int len)
1471 {
1472         int i, errno;
1473         char *ptr;
1474
1475         if (len < 0)
1476                 return -EINVAL;
1477         down_read(&uts_sem);
1478         ptr = vx_new_uts(nodename);
1479         i = 1 + strlen(ptr);
1480         if (i > len)
1481                 i = len;
1482         errno = 0;
1483         if (copy_to_user(name, ptr, i))
1484                 errno = -EFAULT;
1485         up_read(&uts_sem);
1486         return errno;
1487 }
1488
1489 #endif
1490
1491 /*
1492  * Only setdomainname; getdomainname can be implemented by calling
1493  * uname()
1494  */
1495 asmlinkage long sys_setdomainname(char __user *name, int len)
1496 {
1497         int errno;
1498         char tmp[__NEW_UTS_LEN];
1499
1500         if (!capable(CAP_SYS_ADMIN) && !vx_ccaps(VXC_SET_UTSNAME))
1501                 return -EPERM;
1502         if (len < 0 || len > __NEW_UTS_LEN)
1503                 return -EINVAL;
1504
1505         down_write(&uts_sem);
1506         errno = -EFAULT;
1507         if (!copy_from_user(tmp, name, len)) {
1508                 char *ptr = vx_new_uts(domainname);
1509
1510                 memcpy(ptr, tmp, len);
1511                 ptr[len] = 0;
1512                 errno = 0;
1513         }
1514         up_write(&uts_sem);
1515         return errno;
1516 }
1517
1518 asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit __user *rlim)
1519 {
1520         if (resource >= RLIM_NLIMITS)
1521                 return -EINVAL;
1522         else
1523                 return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
1524                         ? -EFAULT : 0;
1525 }
1526
1527 #ifdef __ARCH_WANT_SYS_OLD_GETRLIMIT
1528
1529 /*
1530  *      Back compatibility for getrlimit. Needed for some apps.
1531  */
1532  
1533 asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit __user *rlim)
1534 {
1535         struct rlimit x;
1536         if (resource >= RLIM_NLIMITS)
1537                 return -EINVAL;
1538
1539         memcpy(&x, current->rlim + resource, sizeof(*rlim));
1540         if(x.rlim_cur > 0x7FFFFFFF)
1541                 x.rlim_cur = 0x7FFFFFFF;
1542         if(x.rlim_max > 0x7FFFFFFF)
1543                 x.rlim_max = 0x7FFFFFFF;
1544         return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0;
1545 }
1546
1547 #endif
1548
1549 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit __user *rlim)
1550 {
1551         struct rlimit new_rlim, *old_rlim;
1552         int retval;
1553
1554         if (resource >= RLIM_NLIMITS)
1555                 return -EINVAL;
1556         if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
1557                 return -EFAULT;
1558        if (new_rlim.rlim_cur > new_rlim.rlim_max)
1559                return -EINVAL;
1560         old_rlim = current->rlim + resource;
1561         if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
1562              (new_rlim.rlim_max > old_rlim->rlim_max)) &&
1563             !capable(CAP_SYS_RESOURCE) && !vx_ccaps(VXC_SET_RLIMIT))
1564                 return -EPERM;
1565         if (resource == RLIMIT_NOFILE) {
1566                 if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
1567                         return -EPERM;
1568         }
1569
1570         retval = security_task_setrlimit(resource, &new_rlim);
1571         if (retval)
1572                 return retval;
1573
1574         *old_rlim = new_rlim;
1575         return 0;
1576 }
1577
1578 /*
1579  * It would make sense to put struct rusage in the task_struct,
1580  * except that would make the task_struct be *really big*.  After
1581  * task_struct gets moved into malloc'ed memory, it would
1582  * make sense to do this.  It will make moving the rest of the information
1583  * a lot simpler!  (Which we're not doing right now because we're not
1584  * measuring them yet).
1585  *
1586  * This is SMP safe.  Either we are called from sys_getrusage on ourselves
1587  * below (we know we aren't going to exit/disappear and only we change our
1588  * rusage counters), or we are called from wait4() on a process which is
1589  * either stopped or zombied.  In the zombied case the task won't get
1590  * reaped till shortly after the call to getrusage(), in both cases the
1591  * task being examined is in a frozen state so the counters won't change.
1592  */
1593 int getrusage(struct task_struct *p, int who, struct rusage __user *ru)
1594 {
1595         struct rusage r;
1596
1597         memset((char *) &r, 0, sizeof(r));
1598         switch (who) {
1599                 case RUSAGE_SELF:
1600                         jiffies_to_timeval(p->utime, &r.ru_utime);
1601                         jiffies_to_timeval(p->stime, &r.ru_stime);
1602                         r.ru_nvcsw = p->nvcsw;
1603                         r.ru_nivcsw = p->nivcsw;
1604                         r.ru_minflt = p->min_flt;
1605                         r.ru_majflt = p->maj_flt;
1606                         break;
1607                 case RUSAGE_CHILDREN:
1608                         jiffies_to_timeval(p->cutime, &r.ru_utime);
1609                         jiffies_to_timeval(p->cstime, &r.ru_stime);
1610                         r.ru_nvcsw = p->cnvcsw;
1611                         r.ru_nivcsw = p->cnivcsw;
1612                         r.ru_minflt = p->cmin_flt;
1613                         r.ru_majflt = p->cmaj_flt;
1614                         break;
1615                 default:
1616                         jiffies_to_timeval(p->utime + p->cutime, &r.ru_utime);
1617                         jiffies_to_timeval(p->stime + p->cstime, &r.ru_stime);
1618                         r.ru_nvcsw = p->nvcsw + p->cnvcsw;
1619                         r.ru_nivcsw = p->nivcsw + p->cnivcsw;
1620                         r.ru_minflt = p->min_flt + p->cmin_flt;
1621                         r.ru_majflt = p->maj_flt + p->cmaj_flt;
1622                         break;
1623         }
1624         return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
1625 }
1626
1627 asmlinkage long sys_getrusage(int who, struct rusage __user *ru)
1628 {
1629         if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
1630                 return -EINVAL;
1631         return getrusage(current, who, ru);
1632 }
1633
1634 asmlinkage long sys_umask(int mask)
1635 {
1636         mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
1637         return mask;
1638 }
1639     
1640 asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1641                           unsigned long arg4, unsigned long arg5)
1642 {
1643         int error;
1644         int sig;
1645
1646         error = security_task_prctl(option, arg2, arg3, arg4, arg5);
1647         if (error)
1648                 return error;
1649
1650         switch (option) {
1651                 case PR_SET_PDEATHSIG:
1652                         sig = arg2;
1653                         if (sig < 0 || sig > _NSIG) {
1654                                 error = -EINVAL;
1655                                 break;
1656                         }
1657                         current->pdeath_signal = sig;
1658                         break;
1659                 case PR_GET_PDEATHSIG:
1660                         error = put_user(current->pdeath_signal, (int __user *)arg2);
1661                         break;
1662                 case PR_GET_DUMPABLE:
1663                         if (current->mm->dumpable)
1664                                 error = 1;
1665                         break;
1666                 case PR_SET_DUMPABLE:
1667                         if (arg2 != 0 && arg2 != 1) {
1668                                 error = -EINVAL;
1669                                 break;
1670                         }
1671                         current->mm->dumpable = arg2;
1672                         break;
1673
1674                 case PR_SET_UNALIGN:
1675                         error = SET_UNALIGN_CTL(current, arg2);
1676                         break;
1677                 case PR_GET_UNALIGN:
1678                         error = GET_UNALIGN_CTL(current, arg2);
1679                         break;
1680                 case PR_SET_FPEMU:
1681                         error = SET_FPEMU_CTL(current, arg2);
1682                         break;
1683                 case PR_GET_FPEMU:
1684                         error = GET_FPEMU_CTL(current, arg2);
1685                         break;
1686                 case PR_SET_FPEXC:
1687                         error = SET_FPEXC_CTL(current, arg2);
1688                         break;
1689                 case PR_GET_FPEXC:
1690                         error = GET_FPEXC_CTL(current, arg2);
1691                         break;
1692                 case PR_GET_TIMING:
1693                         error = PR_TIMING_STATISTICAL;
1694                         break;
1695                 case PR_SET_TIMING:
1696                         if (arg2 == PR_TIMING_STATISTICAL)
1697                                 error = 0;
1698                         else
1699                                 error = -EINVAL;
1700                         break;
1701
1702                 case PR_GET_KEEPCAPS:
1703                         if (current->keep_capabilities)
1704                                 error = 1;
1705                         break;
1706                 case PR_SET_KEEPCAPS:
1707                         if (arg2 != 0 && arg2 != 1) {
1708                                 error = -EINVAL;
1709                                 break;
1710                         }
1711                         current->keep_capabilities = arg2;
1712                         break;
1713                 default:
1714                         error = -EINVAL;
1715                         break;
1716         }
1717         return error;
1718 }