Ядро Linux в комментариях

       

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, &current->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(&current->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


Содержание раздела