kernel/sys.c
29140 /*
29141 * linux/kernel/sys.c
29142 *
29143 * Copyright (C) 1991, 1992 Linus Torvalds
29144 */
29145
29146 #include <linux/mm.h>
29147 #include <linux/utsname.h>
29148 #include <linux/mman.h>
29149 #include <linux/smp_lock.h>
29150 #include <linux/notifier.h>
29151 #include <linux/reboot.h>
29152 #include <linux/prctl.h>
29153
29154 #include <asm/uaccess.h>
29155 #include <asm/io.h>
29156
29157 /* this indicates whether you can reboot with
29158 * ctrl-alt-del: the default is yes */
29159
29160 int C_A_D = 1;
29161
29162
29163 /* Notifier list for kernel code which wants to be called
29164 * at shutdown. This is used to stop any idling DMA
29165 * operations and the like. */
29166
29167 struct notifier_block *reboot_notifier_list = NULL;
29168
29169 int register_reboot_notifier(struct notifier_block * nb)
29170 {
29171 return notifier_chain_register(&reboot_notifier_list,
29172 nb);
29173 }
29174
29175 int unregister_reboot_notifier(struct notifier_block *nb)
29176 {
29177 return notifier_chain_unregister(&reboot_notifier_list,
29178 nb);
29179 }
29180
29181
29182
29183 extern void adjust_clock(void);
29184
29185 asmlinkage int sys_ni_syscall(void)
29186 {
29187 return -ENOSYS;
29188 }
29189
29190 static int proc_sel(struct task_struct *p, int which,
29191 int who)
29192 {
29193 if(p->pid)
29194 {
29195 switch (which) {
29196 case PRIO_PROCESS:
29197 if (!who && p == current)
29198 return 1;
29199 return(p->pid == who);
29200 case PRIO_PGRP:
29201 if (!who)
29202 who = current->pgrp;
29203 return(p->pgrp == who);
29204 case PRIO_USER:
29205 if (!who)
29206 who = current->uid;
29207 return(p->uid == who);
29208 }
29209 }
29210 return 0;
29211 }
29212
29213 asmlinkage int sys_setpriority(int which, int who,
29214 int niceval)
29215 {
29216 struct task_struct *p;
29217 unsigned int priority;
29218 int error;
29219
29220 if (which > 2 || which < 0)
29221 return -EINVAL;
29222
29223 /* normalize: avoid signed division
29224 * (rounding problems) */
29225 error = ESRCH;
29226 priority = niceval;
29227 if (niceval < 0)
29228 priority = -niceval;
29229 if (priority > 20)
29230 priority = 20;
29231 priority = (priority * DEF_PRIORITY + 10) / 20 +
29232 DEF_PRIORITY;
29233
29234 if (niceval >= 0) {
29235 priority = 2*DEF_PRIORITY - priority;
29236 if (!priority)
29237 priority = 1;
29238 }
29239
29240 read_lock(&tasklist_lock);
29241 for_each_task(p) {
29242 if (!proc_sel(p, which, who))
29243 continue;
29244 if (p->uid != current->euid &&
29245 p->uid != current->uid && !capable(CAP_SYS_NICE)) {
29246 error = EPERM;
29247 continue;
29248 }
29249 if (error == ESRCH)
29250 error = 0;
29251 if (priority > p->priority && !capable(CAP_SYS_NICE))
29252 error = EACCES;
29253 else
29254 p->priority = priority;
29255 }
29256 read_unlock(&tasklist_lock);
29257
29258 return -error;
29259 }
29260
29261 /* Ugh. To avoid negative return values, "getpriority()"
29262 * will not return the normal nice-value, but a value
29263 * that has been offset by 20 (ie it returns 0..40
29264 * instead of -20..20) */
29265 asmlinkage int sys_getpriority(int which, int who)
29266 {
29267 struct task_struct *p;
29268 long max_prio = -ESRCH;
29269
29270 if (which > 2 || which < 0)
29271 return -EINVAL;
29272
29273 read_lock(&tasklist_lock);
29274 for_each_task (p) {
29275 if (!proc_sel(p, which, who))
29276 continue;
29277 if (p->priority > max_prio)
29278 max_prio = p->priority;
29279 }
29280 read_unlock(&tasklist_lock);
29281
29282 /* scale the priority from timeslice to 0..40 */
29283 if (max_prio > 0)
29284 max_prio = (max_prio * 20 + DEF_PRIORITY/2) /
29285 DEF_PRIORITY;
29286 return max_prio;
29287 }
29288
29289
29290 /* Reboot system call: for obvious reasons only root may
29291 * call it, and even root needs to set up some magic
29292 * numbers in the registers so that some mistake won't
29293 * make this reboot the whole machine. You can also set
29294 * the meaning of the ctrl-alt-del-key here.
29295 *
29296 * reboot doesn't sync: do that yourself before calling
29297 * this. */
29298 asmlinkage int sys_reboot(int magic1, int magic2,
29299 int cmd, void * arg)
29300 {
29301 char buffer[256];
29302
29303 /* We only trust the superuser with rebooting the
29304 * system. */
29305 if (!capable(CAP_SYS_BOOT))
29306 return -EPERM;
29307
29308 /* For safety, we require "magic" arguments. */
29309 if (magic1 != LINUX_REBOOT_MAGIC1 ||
29310 (magic2 != LINUX_REBOOT_MAGIC2 &&
29311 magic2 != LINUX_REBOOT_MAGIC2A &&
29312 magic2 != LINUX_REBOOT_MAGIC2B))
29313 return -EINVAL;
29314
29315 lock_kernel();
29316 switch (cmd) {
29317 case LINUX_REBOOT_CMD_RESTART:
29318 notifier_call_chain(&reboot_notifier_list,
29319 SYS_RESTART, NULL);
29320 printk(KERN_EMERG "Restarting system.\n");
29321 machine_restart(NULL);
29322 break;
29323
29324 case LINUX_REBOOT_CMD_CAD_ON:
29325 C_A_D = 1;
29326 break;
29327
29328 case LINUX_REBOOT_CMD_CAD_OFF:
29329 C_A_D = 0;
29330 break;
29331
29332 case LINUX_REBOOT_CMD_HALT:
29333 notifier_call_chain(&reboot_notifier_list,
29334 SYS_HALT, NULL);
29335 printk(KERN_EMERG "System halted.\n");
29336 machine_halt();
29337 do_exit(0);
29338 break;
29339
29340 case LINUX_REBOOT_CMD_POWER_OFF:
29341 notifier_call_chain(&reboot_notifier_list,
29342 SYS_POWER_OFF, NULL);
29343 printk(KERN_EMERG "Power down.\n");
29344 machine_power_off();
29345 do_exit(0);
29346 break;
29347
29348 case LINUX_REBOOT_CMD_RESTART2:
29349 if (strncpy_from_user(&buffer[0], (char *)arg,
29350 sizeof(buffer) - 1) < 0) {
29351 unlock_kernel();
29352 return -EFAULT;
29353 }
29354 buffer[sizeof(buffer) - 1] = '\0';
29355
29356 notifier_call_chain(&reboot_notifier_list,
29357 SYS_RESTART, buffer);
29358 printk(KERN_EMERG
29359 "Restarting system with command '%s'.\n",
29360 buffer);
29361 machine_restart(buffer);
29362 break;
29363
29364 default:
29365 unlock_kernel();
29366 return -EINVAL;
29367 break;
29368 };
29369 unlock_kernel();
29370 return 0;
29371 }
29372
29373 /* This function gets called by ctrl-alt-del - ie the
29374 * keyboard interrupt. As it's called within an
29375 * interrupt, it may NOT sync: the only choice is whether
29376 * to reboot at once, or just ignore the ctrl-alt-del.
29377 */
29378 void ctrl_alt_del(void)
29379 {
29380 if (C_A_D) {
29381 notifier_call_chain(&reboot_notifier_list,
29382 SYS_RESTART, NULL);
29383 machine_restart(NULL);
29384 } else
29385 kill_proc(1, SIGINT, 1);
29386 }
29387
29388
29389 /* Unprivileged users may change the real gid to the
29390 * effective gid or vice versa. (BSD-style)
29391 *
29392 * If you set the real gid at all, or set the effective
29393 * gid to a value not equal to the real gid, then the
29394 * saved gid is set to the new effective gid.
29395 *
29396 * This makes it possible for a setgid program to
29397 * completely drop its privileges, which is often a
29398 * useful assertion to make when you are doing a security
29399 * audit over a program.
29400 *
29401 * The general idea is that a program which uses just
29402 * setregid() will be 100% compatible with BSD. A
29403 * program which uses just setgid() will be 100%
29404 * compatible with POSIX with saved IDs.
29405 *
29406 * SMP: There are not races, the GIDs are checked only by
29407 * filesystem operations (as far as semantic preservation
29408 * is concerned). */
29409 asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
29410 {
29411 int old_rgid = current->gid;
29412 int old_egid = current->egid;
29413
29414 if (rgid != (gid_t) -1) {
29415 if ((old_rgid == rgid) ||
29416 (current->egid==rgid) ||
29417 capable(CAP_SETGID))
29418 current->gid = rgid;
29419 else
29420 return -EPERM;
29421 }
29422 if (egid != (gid_t) -1) {
29423 if ((old_rgid == egid) ||
29424 (current->egid == egid) ||
29425 (current->sgid == egid) ||
29426 capable(CAP_SETGID))
29427 current->fsgid = current->egid = egid;
29428 else {
29429 current->gid = old_rgid;
29430 return -EPERM;
29431 }
29432 }
29433 if (rgid != (gid_t) -1 ||
29434 (egid != (gid_t) -1 && egid != old_rgid))
29435 current->sgid = current->egid;
29436 current->fsgid = current->egid;
29437 if (current->egid != old_egid)
29438 current->dumpable = 0;
29439 return 0;
29440 }
29441
29442 /* setgid() is implemented like SysV w/ SAVED_IDS
29443 *
29444 * SMP: Same implicit races as above. */
29445 asmlinkage int sys_setgid(gid_t gid)
29446 {
29447 int old_egid = current->egid;
29448
29449 if (capable(CAP_SETGID))
29450 current->gid = current->egid = current->sgid =
29451 current->fsgid = gid;
29452 else if ((gid == current->gid) ||
29453 (gid == current->sgid))
29454 current->egid = current->fsgid = gid;
29455 else
29456 return -EPERM;
29457
29458 if (current->egid != old_egid)
29459 current->dumpable = 0;
29460 return 0;
29461 }
29462
29463 /* cap_emulate_setxuid() fixes the effective / permitted
29464 * capabilities of a process after a call to setuid,
29465 * setreuid, or setresuid.
29466 *
29467 * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_
29468 * all of {r,e,s}uid != 0, the permitted and effective
29469 * capabilities are cleared.
29470 *
29471 * 2) When set*uiding _from_ euid == 0 _to_ euid != 0,
29472 * the effective capabilities of the process are
29473 * cleared.
29474 *
29475 * 3) When set*uiding _from_ euid != 0 _to_ euid == 0,
29476 * the effective capabilities are set to the permitted
29477 * capabilities.
29478 *
29479 * fsuid is handled elsewhere. fsuid == 0 and
29480 * {r,e,s}uid!= 0 should never happen.
29481 *
29482 * -astor */
29483 extern inline void cap_emulate_setxuid(int old_ruid,
29484 int old_euid,
29485 int old_suid)
29486 {
29487 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0)
29488 && (current->uid != 0 && current->euid != 0 &&
29489 current->suid != 0)) {
29490 cap_clear(current->cap_permitted);
29491 cap_clear(current->cap_effective);
29492 }
29493 if (old_euid == 0 && current->euid != 0) {
29494 cap_clear(current->cap_effective);
29495 }
29496 if (old_euid != 0 && current->euid == 0) {
29497 current->cap_effective = current->cap_permitted;
29498 }
29499 }
29500
29501 /* Unprivileged users may change the real uid to the
29502 * effective uid or vice versa. (BSD-style)
29503 *
29504 * If you set the real uid at all, or set the effective
29505 * uid to a value not equal to the real uid, then the
29506 * saved uid is set to the new effective uid.
29507 *
29508 * This makes it possible for a setuid program to
29509 * completely drop its privileges, which is often a
29510 * useful assertion to make when you are doing a security
29511 * audit over a program.
29512 *
29513 * The general idea is that a program which uses just
29514 * setreuid() will be 100% compatible with BSD. A
29515 * program which uses just setuid() will be 100%
29516 * compatible with POSIX with saved IDs. */
29517 asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
29518 {
29519 int old_ruid, old_euid, old_suid, new_ruid;
29520
29521 new_ruid = old_ruid = current->uid;
29522 old_euid = current->euid;
29523 old_suid = current->suid;
29524 if (ruid != (uid_t) -1) {
29525 if ((old_ruid == ruid) ||
29526 (current->euid==ruid) ||
29527 capable(CAP_SETUID))
29528 new_ruid = ruid;
29529 else
29530 return -EPERM;
29531 }
29532 if (euid != (uid_t) -1) {
29533 if ((old_ruid == euid) ||
29534 (current->euid == euid) ||
29535 (current->suid == euid) ||
29536 capable(CAP_SETUID))
29537 current->fsuid = current->euid = euid;
29538 else
29539 return -EPERM;
29540 }
29541 if (ruid != (uid_t) -1 ||
29542 (euid != (uid_t) -1 && euid != old_ruid))
29543 current->suid = current->euid;
29544 current->fsuid = current->euid;
29545 if (current->euid != old_euid)
29546 current->dumpable = 0;
29547
29548 if(new_ruid != old_ruid) {
29549 /* What if a process setreuid()'s and this brings the
29550 * new uid over his NPROC rlimit? We can check this
29551 * now cheaply with the new uid cache, so if it
29552 * matters we should be checking for it. -DaveM */
29553 free_uid(current);
29554 current->uid = new_ruid;
29555 alloc_uid(current);
29556 }
29557
29558 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
29559 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
29560 }
29561
29562 return 0;
29563 }
29564
29565
29566
29567 /* setuid() is implemented like SysV with SAVED_IDS
29568 *
29569 * Note that SAVED_ID's is deficient in that a setuid
29570 * root program like sendmail, for example, cannot set
29571 * its uid to be a normal user and then switch back,
29572 * because if you're root, setuid() sets the saved uid
29573 * too. If you don't like this, blame the bright people
29574 * in the POSIX committee and/or USG. Note that the
29575 * BSD-style setreuid() will allow a root program to
29576 * temporarily drop privileges and be able to regain them
29577 * by swapping the real and effective uid. */
29578 asmlinkage int sys_setuid(uid_t uid)
29579 {
29580 int old_euid = current->euid;
29581 int old_ruid, old_suid, new_ruid;
29582
29583 old_ruid = new_ruid = current->uid;
29584 old_suid = current->suid;
29585 if (capable(CAP_SETUID))
29586 new_ruid = current->euid = current->suid =
29587 current->fsuid = uid;
29588 else if ((uid == current->uid) ||
29589 (uid == current->suid))
29590 current->fsuid = current->euid = uid;
29591 else
29592 return -EPERM;
29593
29594 if (current->euid != old_euid)
29595 current->dumpable = 0;
29596
29597 if (new_ruid != old_ruid) {
29598 /* See comment above about NPROC rlimit issues... */
29599 free_uid(current);
29600 current->uid = new_ruid;
29601 alloc_uid(current);
29602 }
29603
29604 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
29605 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
29606 }
29607
29608 return 0;
29609 }
29610
29611
29612 /* This function implements a generic ability to update
29613 * ruid, euid, and suid. This allows you to implement
29614 * the 4.4 compatible seteuid(). */
29615 asmlinkage int sys_setresuid(uid_t ruid, uid_t euid,
29616 uid_t suid)
29617 {
29618 int old_ruid = current->uid;
29619 int old_euid = current->euid;
29620 int old_suid = current->suid;
29621
29622 if (!capable(CAP_SETUID)) {
29623 if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
29624 (ruid != current->euid) &&
29625 (ruid != current->suid))
29626 return -EPERM;
29627 if ((euid != (uid_t) -1) && (euid != current->uid) &&
29628 (euid != current->euid) &&
29629 (euid != current->suid))
29630 return -EPERM;
29631 if ((suid != (uid_t) -1) && (suid != current->uid) &&
29632 (suid != current->euid) &&
29633 (suid != current->suid))
29634 return -EPERM;
29635 }
29636 if (ruid != (uid_t) -1) {
29637 /* See above commentary about NPROC rlimit issues
29638 * here. */
29639 free_uid(current);
29640 current->uid = ruid;
29641 alloc_uid(current);
29642 }
29643 if (euid != (uid_t) -1) {
29644 if (euid != current->euid)
29645 current->dumpable = 0;
29646 current->euid = euid;
29647 current->fsuid = euid;
29648 }
29649 if (suid != (uid_t) -1)
29650 current->suid = suid;
29651
29652 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
29653 cap_emulate_setxuid(old_ruid, old_euid, old_suid);
29654 }
29655
29656 return 0;
29657 }
29658
29659 asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid,
29660 uid_t *suid)
29661 {
29662 int retval;
29663
29664 if (!(retval = put_user(current->uid, ruid)) &&
29665 !(retval = put_user(current->euid, euid)))
29666 retval = put_user(current->suid, suid);
29667
29668 return retval;
29669 }
29670
29671 /* Same as above, but for rgid, egid, sgid. */
29672 asmlinkage int sys_setresgid(gid_t rgid, gid_t egid,
29673 gid_t sgid)
29674 {
29675 if (!capable(CAP_SETGID)) {
29676 if ((rgid != (gid_t) -1) &&
29677 (rgid != current->gid) &&
29678 (rgid != current->egid) &&
29679 (rgid != current->sgid))
29680 return -EPERM;
29681 if ((egid != (gid_t) -1) &&
29682 (egid != current->gid) &&
29683 (egid != current->egid) &&
29684 (egid != current->sgid))
29685 return -EPERM;
29686 if ((sgid != (gid_t) -1) &&
29687 (sgid != current->gid) &&
29688 (sgid != current->egid) &&
29689 (sgid != current->sgid))
29690 return -EPERM;
29691 }
29692 if (rgid != (gid_t) -1)
29693 current->gid = rgid;
29694 if (egid != (gid_t) -1) {
29695 if (egid != current->egid)
29696 current->dumpable = 0;
29697 current->egid = egid;
29698 current->fsgid = egid;
29699 }
29700 if (sgid != (gid_t) -1)
29701 current->sgid = sgid;
29702 return 0;
29703 }
29704
29705 asmlinkage int sys_getresgid(gid_t *rgid, gid_t *egid,
29706 gid_t *sgid)
29707 {
29708 int retval;
29709
29710 if (!(retval = put_user(current->gid, rgid)) &&
29711 !(retval = put_user(current->egid, egid)))
29712 retval = put_user(current->sgid, sgid);
29713
29714 return retval;
29715 }
29716
29717
29718 /* "setfsuid()" sets the fsuid - the uid used for
29719 * filesystem checks. This is used for "access()" and for
29720 * the NFS daemon (letting nfsd stay at whatever uid it
29721 * wants to). It normally shadows "euid", except when
29722 * explicitly set by setfsuid() or for access.. */
29723 asmlinkage int sys_setfsuid(uid_t uid)
29724 {
29725 int old_fsuid;
29726
29727 old_fsuid = current->fsuid;
29728 if (uid == current->uid || uid == current->euid ||
29729 uid == current->suid || uid == current->fsuid ||
29730 capable(CAP_SETUID))
29731 current->fsuid = uid;
29732 if (current->fsuid != old_fsuid)
29733 current->dumpable = 0;
29734
29735 /* We emulate fsuid by essentially doing a scaled-down
29736 * version of what we did in setresuid and
29737 * friends. However, we only operate on the fs-specific
29738 * bits of the process' effective capabilities
29739 *
29740 * FIXME - is fsuser used for all CAP_FS_MASK
29741 * capabilities? if not, we might be a bit too harsh
29742 * here. */
29743 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
29744 if (old_fsuid == 0 && current->fsuid != 0) {
29745 cap_t(current->cap_effective) &= ~CAP_FS_MASK;
29746 }
29747 if (old_fsuid != 0 && current->fsuid == 0) {
29748 cap_t(current->cap_effective) |=
29749 (cap_t(current->cap_permitted) & CAP_FS_MASK);
29750 }
29751 }
29752
29753 return old_fsuid;
29754 }
29755
29756 /* Samma pе svenska. */
29757 asmlinkage int sys_setfsgid(gid_t gid)
29758 {
29759 int old_fsgid;
29760
29761 old_fsgid = current->fsgid;
29762 if (gid == current->gid || gid == current->egid ||
29763 gid == current->sgid || gid == current->fsgid ||
29764 capable(CAP_SETGID))
29765 current->fsgid = gid;
29766 if (current->fsgid != old_fsgid)
29767 current->dumpable = 0;
29768
29769 return old_fsgid;
29770 }
29771
29772 asmlinkage long sys_times(struct tms * tbuf)
29773 {
29774 /* In the SMP world we might just be unlucky and have
29775 * one of the times increment as we use it. Since the
29776 * value is an atomically safe type this is just
29777 * fine. Conceptually it's as if the syscall took an
29778 * instant longer to occur. */
29779 if (tbuf)
29780 if (copy_to_user(tbuf, ¤t->times,
29781 sizeof(struct tms)))
29782 return -EFAULT;
29783 return jiffies;
29784 }
29785
29786 /* This needs some heavy checking ... I just haven't the
29787 * stomach for it. I also don't fully understand
29788 * sessions/pgrp etc. Let somebody who does explain it.
29789 *
29790 * OK, I think I have the protection semantics
29791 * right.... this is really only important on a
29792 * multi-user system anyway, to make sure one user can't
29793 * send a signal to a process owned by another. -TYT,
29794 * 12/12/91
29795 *
29796 * Auch. Had to add the 'did_exec' flag to conform
29797 * completely to POSIX. LBT 04.03.94 */
29798 asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
29799 {
29800 struct task_struct * p;
29801 int err = -EINVAL;
29802
29803 if (!pid)
29804 pid = current->pid;
29805 if (!pgid)
29806 pgid = pid;
29807 if (pgid < 0)
29808 return -EINVAL;
29809
29810 /* From this point forward we keep holding onto the
29811 * tasklist lock so that our parent does not change
29812 * from under us. -DaveM */
29813 read_lock(&tasklist_lock);
29814
29815 err = -ESRCH;
29816 p = find_task_by_pid(pid);
29817 if (!p)
29818 goto out;
29819
29820 if (p->p_pptr == current || p->p_opptr == current) {
29821 err = -EPERM;
29822 if (p->session != current->session)
29823 goto out;
29824 err = -EACCES;
29825 if (p->did_exec)
29826 goto out;
29827 } else if (p != current)
29828 goto out;
29829 err = -EPERM;
29830 if (p->leader)
29831 goto out;
29832 if (pgid != pid) {
29833 struct task_struct * tmp;
29834 for_each_task (tmp) {
29835 if (tmp->pgrp == pgid &&
29836 tmp->session == current->session)
29837 goto ok_pgid;
29838 }
29839 goto out;
29840 }
29841
29842 ok_pgid:
29843 p->pgrp = pgid;
29844 err = 0;
29845 out:
29846 /* All paths lead to here, thus we are safe. -DaveM */
29847 read_unlock(&tasklist_lock);
29848 return err;
29849 }
29850
29851 asmlinkage int sys_getpgid(pid_t pid)
29852 {
29853 if (!pid) {
29854 return current->pgrp;
29855 } else {
29856 int retval;
29857 struct task_struct *p;
29858
29859 read_lock(&tasklist_lock);
29860 p = find_task_by_pid(pid);
29861
29862 retval = -ESRCH;
29863 if (p)
29864 retval = p->pgrp;
29865 read_unlock(&tasklist_lock);
29866 return retval;
29867 }
29868 }
29869
29870 asmlinkage int sys_getpgrp(void)
29871 {
29872 /* SMP: assuming writes are word atomic this is fine */
29873 return current->pgrp;
29874 }
29875
29876 asmlinkage int sys_getsid(pid_t pid)
29877 {
29878 if (!pid) {
29879 return current->session;
29880 } else {
29881 int retval;
29882 struct task_struct *p;
29883
29884 read_lock(&tasklist_lock);
29885 p = find_task_by_pid(pid);
29886
29887 retval = -ESRCH;
29888 if(p)
29889 retval = p->session;
29890 read_unlock(&tasklist_lock);
29891 return retval;
29892 }
29893 }
29894
29895 asmlinkage int sys_setsid(void)
29896 {
29897 struct task_struct * p;
29898 int err = -EPERM;
29899
29900 read_lock(&tasklist_lock);
29901 for_each_task(p) {
29902 if (p->pgrp == current->pid)
29903 goto out;
29904 }
29905
29906 current->leader = 1;
29907 current->session = current->pgrp = current->pid;
29908 current->tty = NULL;
29909 current->tty_old_pgrp = 0;
29910 err = current->pgrp;
29911 out:
29912 read_unlock(&tasklist_lock);
29913 return err;
29914 }
29915
29916 /* Supplementary group IDs */
29917 asmlinkage int sys_getgroups(int gidsetsize,
29918 gid_t *grouplist)
29919 {
29920 int i;
29921
29922 /* SMP: Nobody else can change our grouplist. Thus we
29923 * are safe. */
29924 if (gidsetsize < 0)
29925 return -EINVAL;
29926 i = current->ngroups;
29927 if (gidsetsize) {
29928 if (i > gidsetsize)
29929 return -EINVAL;
29930 if (copy_to_user(grouplist, current->groups,
29931 sizeof(gid_t)*i))
29932 return -EFAULT;
29933 }
29934 return i;
29935 }
29936
29937 /* SMP: Our groups are not shared. We can copy to/from
29938 * them safely without another task interfering. */
29939 asmlinkage int sys_setgroups(int gidsetsize,
29940 gid_t *grouplist)
29941 {
29942 if (!capable(CAP_SETGID))
29943 return -EPERM;
29944 if ((unsigned) gidsetsize > NGROUPS)
29945 return -EINVAL;
29946 if (copy_from_user(current->groups, grouplist,
29947 gidsetsize * sizeof(gid_t)))
29948 return -EFAULT;
29949 current->ngroups = gidsetsize;
29950 return 0;
29951 }
29952
29953 int in_group_p(gid_t grp)
29954 {
29955 if (grp != current->fsgid) {
29956 int i = current->ngroups;
29957 if (i) {
29958 gid_t *groups = current->groups;
29959 do {
29960 if (*groups == grp)
29961 goto out;
29962 groups++;
29963 i--;
29964 } while (i);
29965 }
29966 return 0;
29967 }
29968 out:
29969 return 1;
29970 }
29971
29972 /* This should really be a blocking read-write lock
29973 * rather than a semaphore. Anybody want to implement
29974 * one? */
29975 struct semaphore uts_sem = MUTEX;
29976
29977 asmlinkage int sys_newuname(struct new_utsname * name)
29978 {
29979 int errno = 0;
29980
29981 down(&uts_sem);
29982 if (copy_to_user(name,&system_utsname,sizeof *name))
29983 errno = -EFAULT;
29984 up(&uts_sem);
29985 return errno;
29986 }
29987
29988 asmlinkage int sys_sethostname(char *name, int len)
29989 {
29990 int errno;
29991
29992 if (!capable(CAP_SYS_ADMIN))
29993 return -EPERM;
29994 if (len < 0 || len > __NEW_UTS_LEN)
29995 return -EINVAL;
29996 down(&uts_sem);
29997 errno = -EFAULT;
29998 if (!copy_from_user(system_utsname.nodename, name,
29999 len)) {
30000 system_utsname.nodename[len] = 0;
30001 errno = 0;
30002 }
30003 up(&uts_sem);
30004 return errno;
30005 }
30006
30007 asmlinkage int sys_gethostname(char *name, int len)
30008 {
30009 int i, errno;
30010
30011 if (len < 0)
30012 return -EINVAL;
30013 down(&uts_sem);
30014 i = 1 + strlen(system_utsname.nodename);
30015 if (i > len)
30016 i = len;
30017 errno = 0;
30018 if (copy_to_user(name, system_utsname.nodename, i))
30019 errno = -EFAULT;
30020 up(&uts_sem);
30021 return errno;
30022 }
30023
30024 /* Only setdomainname; getdomainname can be implemented
30025 * by calling uname() */
30026 asmlinkage int sys_setdomainname(char *name, int len)
30027 {
30028 int errno;
30029
30030 if (!capable(CAP_SYS_ADMIN))
30031 return -EPERM;
30032 if (len < 0 || len > __NEW_UTS_LEN)
30033 return -EINVAL;
30034
30035 down(&uts_sem);
30036 errno = -EFAULT;
30037 if (!copy_from_user(system_utsname.domainname, name,
30038 len)) {
30039 errno = 0;
30040 system_utsname.domainname[len] = 0;
30041 }
30042 up(&uts_sem);
30043 return errno;
30044 }
30045
30046 asmlinkage int sys_getrlimit(unsigned int resource,
30047 struct rlimit *rlim)
30048 {
30049 if (resource >= RLIM_NLIMITS)
30050 return -EINVAL;
30051 else
30052 return copy_to_user(rlim, current->rlim + resource,
30053 sizeof(*rlim))
30054 ? -EFAULT : 0;
30055 }
30056
30057 asmlinkage int sys_setrlimit(unsigned int resource,
30058 struct rlimit *rlim)
30059 {
30060 struct rlimit new_rlim, *old_rlim;
30061
30062 if (resource >= RLIM_NLIMITS)
30063 return -EINVAL;
30064 if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
30065 return -EFAULT;
30066 old_rlim = current->rlim + resource;
30067 if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
30068 (new_rlim.rlim_max > old_rlim->rlim_max)) &&
30069 !capable(CAP_SYS_RESOURCE))
30070 return -EPERM;
30071 if (resource == RLIMIT_NOFILE) {
30072 if (new_rlim.rlim_cur > NR_OPEN ||
30073 new_rlim.rlim_max > NR_OPEN)
30074 return -EPERM;
30075 }
30076 *old_rlim = new_rlim;
30077 return 0;
30078 }
30079
30080 /* It would make sense to put struct rusage in the
30081 * task_struct, except that would make the task_struct be
30082 * *really big*. After task_struct gets moved into
30083 * malloc'ed memory, it would make sense to do this. It
30084 * will make moving the rest of the information a lot
30085 * simpler! (Which we're not doing right now because
30086 * we're not measuring them yet).
30087 *
30088 * This is SMP safe. Either we are called from
30089 * sys_getrusage on ourselves below (we know we aren't
30090 * going to exit/disappear and only we change our rusage
30091 * counters), or we are called from wait4() on a process
30092 * which is either stopped or zombied. In the zombied
30093 * case the task won't get reaped till shortly after the
30094 * call to getrusage(), in both cases the task being
30095 * examined is in a frozen state so the counters won't
30096 * change. */
30097 int getrusage(struct task_struct *p, int who,
30098 struct rusage *ru)
30099 {
30100 struct rusage r;
30101
30102 memset((char *) &r, 0, sizeof(r));
30103 switch (who) {
30104 case RUSAGE_SELF:
30105 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime);
30106 r.ru_utime.tv_usec=CT_TO_USECS(p->times.tms_utime);
30107 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime);
30108 r.ru_stime.tv_usec=CT_TO_USECS(p->times.tms_stime);
30109 r.ru_minflt = p->min_flt;
30110 r.ru_majflt = p->maj_flt;
30111 r.ru_nswap = p->nswap;
30112 break;
30113 case RUSAGE_CHILDREN:
30114 r.ru_utime.tv_sec =
30115 CT_TO_SECS(p->times.tms_cutime);
30116 r.ru_utime.tv_usec =
30117 CT_TO_USECS(p->times.tms_cutime);
30118 r.ru_stime.tv_sec =
30119 CT_TO_SECS(p->times.tms_cstime);
30120 r.ru_stime.tv_usec =
30121 CT_TO_USECS(p->times.tms_cstime);
30122 r.ru_minflt = p->cmin_flt;
30123 r.ru_majflt = p->cmaj_flt;
30124 r.ru_nswap = p->cnswap;
30125 break;
30126 default:
30127 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime
30128 + p->times.tms_cutime);
30129 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime
30130 + p->times.tms_cutime);
30131 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime
30132 + p->times.tms_cstime);
30133 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime
30134 + p->times.tms_cstime);
30135 r.ru_minflt = p->min_flt + p->cmin_flt;
30136 r.ru_majflt = p->maj_flt + p->cmaj_flt;
30137 r.ru_nswap = p->nswap + p->cnswap;
30138 break;
30139 }
30140 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
30141 }
30142
30143 asmlinkage int sys_getrusage(int who, struct rusage *ru)
30144 {
30145 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
30146 return -EINVAL;
30147 return getrusage(current, who, ru);
30148 }
30149
30150 asmlinkage int sys_umask(int mask)
30151 {
30152 mask = xchg(¤t->fs->umask, mask & S_IRWXUGO);
30153 return mask;
30154 }
30155
30156 asmlinkage int sys_prctl(int option, unsigned long arg2,
30157 unsigned long arg3, unsigned long arg4,
30158 unsigned long arg5)
30159 {
30160 int error = 0;
30161 int sig;
30162
30163 switch (option) {
30164 case PR_SET_PDEATHSIG:
30165 sig = arg2;
30166 if (sig > _NSIG) {
30167 error = -EINVAL;
30168 break;
30169 }
30170 current->pdeath_signal = sig;
30171 break;
30172 default:
30173 error = -EINVAL;
30174 break;
30175 }
30176 return error;
30177 }
30178
Сайт управляется системой
uCoz