~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/kernel/sys.c

Version: ~ [ 0.6-2.3.46 ] ~
Architecture: ~ [ um ] ~

** Warning: Cannot open xref database.

1 /* 2 * linux/kernel/sys.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7 #include <linux/mm.h> 8 #include <linux/utsname.h> 9 #include <linux/mman.h> 10 #include <linux/smp_lock.h> 11 #include <linux/notifier.h> 12 #include <linux/reboot.h> 13 #include <linux/prctl.h> 14 #include <linux/init.h> 15 #include <linux/highuid.h> 16 17 #include <asm/uaccess.h> 18 #include <asm/io.h> 19 20 /* 21 * this is where the system-wide overflow UID and GID are defined, for 22 * architectures that now have 32-bit UID/GID but didn't in the past 23 */ 24 25 int overflowuid = DEFAULT_OVERFLOWUID; 26 int overflowgid = DEFAULT_OVERFLOWGID; 27 28 /* 29 * the same as above, but for filesystems which can only store a 16-bit 30 * UID and GID. as such, this is needed on all architectures 31 */ 32 33 int fs_overflowuid = DEFAULT_FS_OVERFLOWUID; 34 int fs_overflowgid = DEFAULT_FS_OVERFLOWUID; 35 36 /* 37 * this indicates whether you can reboot with ctrl-alt-del: the default is yes 38 */ 39 40 int C_A_D = 1; 41 42 43 /* 44 * Notifier list for kernel code which wants to be called 45 * at shutdown. This is used to stop any idling DMA operations 46 * and the like. 47 */ 48 49 struct notifier_block *reboot_notifier_list = NULL; 50 51 int register_reboot_notifier(struct notifier_block * nb) 52 { 53 return notifier_chain_register(&reboot_notifier_list, nb); 54 } 55 56 int unregister_reboot_notifier(struct notifier_block * nb) 57 { 58 return notifier_chain_unregister(&reboot_notifier_list, nb); 59 } 60 61 asmlinkage long sys_ni_syscall(void) 62 { 63 return -ENOSYS; 64 } 65 66 static int proc_sel(struct task_struct *p, int which, int who) 67 { 68 if(p->pid) 69 { 70 switch (which) { 71 case PRIO_PROCESS: 72 if (!who && p == current) 73 return 1; 74 return(p->pid == who); 75 case PRIO_PGRP: 76 if (!who) 77 who = current->pgrp; 78 return(p->pgrp == who); 79 case PRIO_USER: 80 if (!who) 81 who = current->uid; 82 return(p->uid == who); 83 } 84 } 85 return 0; 86 } 87 88 asmlinkage long sys_setpriority(int which, int who, int niceval) 89 { 90 struct task_struct *p; 91 unsigned int priority; 92 int error; 93 94 if (which > 2 || which < 0) 95 return -EINVAL; 96 97 /* normalize: avoid signed division (rounding problems) */ 98 error = ESRCH; 99 priority = niceval; 100 if (niceval < 0) 101 priority = -niceval; 102 if (priority > 20) 103 priority = 20; 104 priority = (priority * DEF_PRIORITY + 10) / 20 + DEF_PRIORITY; 105 106 if (niceval >= 0) { 107 priority = 2*DEF_PRIORITY - priority; 108 if (!priority) 109 priority = 1; 110 } 111 112 read_lock(&tasklist_lock); 113 for_each_task(p) { 114 if (!proc_sel(p, which, who)) 115 continue; 116 if (p->uid != current->euid && 117 p->uid != current->uid && !capable(CAP_SYS_NICE)) { 118 error = EPERM; 119 continue; 120 } 121 if (error == ESRCH) 122 error = 0; 123 if (priority > p->priority && !capable(CAP_SYS_NICE)) 124 error = EACCES; 125 else 126 p->priority = priority; 127 } 128 read_unlock(&tasklist_lock); 129 130 return -error; 131 } 132 133 /* 134 * Ugh. To avoid negative return values, "getpriority()" will 135 * not return the normal nice-value, but a value that has been 136 * offset by 20 (ie it returns 0..40 instead of -20..20) 137 */ 138 asmlinkage long sys_getpriority(int which, int who) 139 { 140 struct task_struct *p; 141 long max_prio = -ESRCH; 142 143 if (which > 2 || which < 0) 144 return -EINVAL; 145 146 read_lock(&tasklist_lock); 147 for_each_task (p) { 148 if (!proc_sel(p, which, who)) 149 continue; 150 if (p->priority > max_prio) 151 max_prio = p->priority; 152 } 153 read_unlock(&tasklist_lock); 154 155 /* scale the priority from timeslice to 0..40 */ 156 if (max_prio > 0) 157 max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY; 158 return max_prio; 159 } 160 161 162 /* 163 * Reboot system call: for obvious reasons only root may call it, 164 * and even root needs to set up some magic numbers in the registers 165 * so that some mistake won't make this reboot the whole machine. 166 * You can also set the meaning of the ctrl-alt-del-key here. 167 * 168 * reboot doesn't sync: do that yourself before calling this. 169 */ 170 asmlinkage long sys_reboot(int magic1, int magic2, int cmd, void * arg) 171 { 172 char buffer[256]; 173 174 /* We only trust the superuser with rebooting the system. */ 175 if (!capable(CAP_SYS_BOOT)) 176 return -EPERM; 177 178 /* For safety, we require "magic" arguments. */ 179 if (magic1 != LINUX_REBOOT_MAGIC1 || 180 (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A && 181 magic2 != LINUX_REBOOT_MAGIC2B)) 182 return -EINVAL; 183 184 lock_kernel(); 185 switch (cmd) { 186 case LINUX_REBOOT_CMD_RESTART: 187 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL); 188 printk(KERN_EMERG "Restarting system.\n"); 189 machine_restart(NULL); 190 break; 191 192 case LINUX_REBOOT_CMD_CAD_ON: 193 C_A_D = 1; 194 break; 195 196 case LINUX_REBOOT_CMD_CAD_OFF: 197 C_A_D = 0; 198 break; 199 200 case LINUX_REBOOT_CMD_HALT: 201 notifier_call_chain(&reboot_notifier_list, SYS_HALT, NULL); 202 printk(KERN_EMERG "System halted.\n"); 203 machine_halt(); 204 do_exit(0); 205 break; 206 207 case LINUX_REBOOT_CMD_POWER_OFF: 208 notifier_call_chain(&reboot_notifier_list, SYS_POWER_OFF, NULL); 209 printk(KERN_EMERG "Power down.\n"); 210 machine_power_off(); 211 do_exit(0); 212 break; 213 214 case LINUX_REBOOT_CMD_RESTART2: 215 if (strncpy_from_user(&buffer[0], (char *)arg, sizeof(buffer) - 1) < 0) { 216 unlock_kernel(); 217 return -EFAULT; 218 } 219 buffer[sizeof(buffer) - 1] = '\0'; 220 221 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, buffer); 222 printk(KERN_EMERG "Restarting system with command '%s'.\n", buffer); 223 machine_restart(buffer); 224 break; 225 226 default: 227 unlock_kernel(); 228 return -EINVAL; 229 break; 230 }; 231 unlock_kernel(); 232 return 0; 233 } 234 235 /* 236 * This function gets called by ctrl-alt-del - ie the keyboard interrupt. 237 * As it's called within an interrupt, it may NOT sync: the only choice 238 * is whether to reboot at once, or just ignore the ctrl-alt-del. 239 */ 240 void ctrl_alt_del(void) 241 { 242 if (C_A_D) { 243 notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL); 244 machine_restart(NULL); 245 } else 246 kill_proc(1, SIGINT, 1); 247 } 248 249 250 /* 251 * Unprivileged users may change the real gid to the effective gid 252 * or vice versa. (BSD-style) 253 * 254 * If you set the real gid at all, or set the effective gid to a value not 255 * equal to the real gid, then the saved gid is set to the new effective gid. 256 * 257 * This makes it possible for a setgid program to completely drop its 258 * privileges, which is often a useful assertion to make when you are doing 259 * a security audit over a program. 260 * 261 * The general idea is that a program which uses just setregid() will be 262 * 100% compatible with BSD. A program which uses just setgid() will be 263 * 100% compatible with POSIX with saved IDs. 264 * 265 * SMP: There are not races, the GIDs are checked only by filesystem 266 * operations (as far as semantic preservation is concerned). 267 */ 268 asmlinkage long sys_setregid(gid_t rgid, gid_t egid) 269 { 270 int old_rgid = current->gid; 271 int old_egid = current->egid; 272 273 if (rgid != (gid_t) -1) { 274 if ((old_rgid == rgid) || 275 (current->egid==rgid) || 276 capable(CAP_SETGID)) 277 current->gid = rgid; 278 else 279 return -EPERM; 280 } 281 if (egid != (gid_t) -1) { 282 if ((old_rgid == egid) || 283 (current->egid == egid) || 284 (current->sgid == egid) || 285 capable(CAP_SETGID)) 286 current->fsgid = current->egid = egid; 287 else { 288 current->gid = old_rgid; 289 return -EPERM; 290 } 291 } 292 if (rgid != (gid_t) -1 || 293 (egid != (gid_t) -1 && egid != old_rgid)) 294 current->sgid = current->egid; 295 current->fsgid = current->egid; 296 if (current->egid != old_egid) 297 current->dumpable = 0; 298 return 0; 299 } 300 301 /* 302 * setgid() is implemented like SysV w/ SAVED_IDS 303 * 304 * SMP: Same implicit races as above. 305 */ 306 asmlinkage long sys_setgid(gid_t gid) 307 { 308 int old_egid = current->egid; 309 310 if (capable(CAP_SETGID)) 311 current->gid = current->egid = current->sgid = current->fsgid = gid; 312 else if ((gid == current->gid) || (gid == current->sgid)) 313 current->egid = current->fsgid = gid; 314 else 315 return -EPERM; 316 317 if (current->egid != old_egid) 318 current->dumpable = 0; 319 return 0; 320 } 321 322 /* 323 * cap_emulate_setxuid() fixes the effective / permitted capabilities of 324 * a process after a call to setuid, setreuid, or setresuid. 325 * 326 * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of 327 * {r,e,s}uid != 0, the permitted and effective capabilities are 328 * cleared. 329 * 330 * 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective 331 * capabilities of the process are cleared. 332 * 333 * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective 334 * capabilities are set to the permitted capabilities. 335 * 336 * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should 337 * never happen. 338 * 339 * -astor 340 */ 341 extern inline void cap_emulate_setxuid(int old_ruid, int old_euid, 342 int old_suid) 343 { 344 if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) && 345 (current->uid != 0 && current->euid != 0 && current->suid != 0)) { 346 cap_clear(current->cap_permitted); 347 cap_clear(current->cap_effective); 348 } 349 if (old_euid == 0 && current->euid != 0) { 350 cap_clear(current->cap_effective); 351 } 352 if (old_euid != 0 && current->euid == 0) { 353 current->cap_effective = current->cap_permitted; 354 } 355 } 356 357 /* 358 * Unprivileged users may change the real uid to the effective uid 359 * or vice versa. (BSD-style) 360 * 361 * If you set the real uid at all, or set the effective uid to a value not 362 * equal to the real uid, then the saved uid is set to the new effective uid. 363 * 364 * This makes it possible for a setuid program to completely drop its 365 * privileges, which is often a useful assertion to make when you are doing 366 * a security audit over a program. 367 * 368 * The general idea is that a program which uses just setreuid() will be 369 * 100% compatible with BSD. A program which uses just setuid() will be 370 * 100% compatible with POSIX with saved IDs. 371 */ 372 asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) 373 { 374 int old_ruid, old_euid, old_suid, new_ruid; 375 376 new_ruid = old_ruid = current->uid; 377 old_euid = current->euid; 378 old_suid = current->suid; 379 if (ruid != (uid_t) -1) { 380 if ((old_ruid == ruid) || 381 (current->euid==ruid) || 382 capable(CAP_SETUID)) 383 new_ruid = ruid; 384 else 385 return -EPERM; 386 } 387 if (euid != (uid_t) -1) { 388 if ((old_ruid == euid) || 389 (current->euid == euid) || 390 (current->suid == euid) || 391 capable(CAP_SETUID)) 392 current->fsuid = current->euid = euid; 393 else 394 return -EPERM; 395 } 396 if (ruid != (uid_t) -1 || 397 (euid != (uid_t) -1 && euid != old_ruid)) 398 current->suid = current->euid; 399 current->fsuid = current->euid; 400 if (current->euid != old_euid) 401 current->dumpable = 0; 402 403 if(new_ruid != old_ruid) { 404 /* What if a process setreuid()'s and this brings the 405 * new uid over his NPROC rlimit? We can check this now 406 * cheaply with the new uid cache, so if it matters 407 * we should be checking for it. -DaveM 408 */ 409 free_uid(current); 410 current->uid = new_ruid; 411 alloc_uid(current); 412 } 413 414 if (!issecure(SECURE_NO_SETUID_FIXUP)) { 415 cap_emulate_setxuid(old_ruid, old_euid, old_suid); 416 } 417 418 return 0; 419 } 420 421 422 423 /* 424 * setuid() is implemented like SysV with SAVED_IDS 425 * 426 * Note that SAVED_ID's is deficient in that a setuid root program 427 * like sendmail, for example, cannot set its uid to be a normal 428 * user and then switch back, because if you're root, setuid() sets 429 * the saved uid too. If you don't like this, blame the bright people 430 * in the POSIX committee and/or USG. Note that the BSD-style setreuid() 431 * will allow a root program to temporarily drop privileges and be able to 432 * regain them by swapping the real and effective uid. 433 */ 434 asmlinkage long sys_setuid(uid_t uid) 435 { 436 int old_euid = current->euid; 437 int old_ruid, old_suid, new_ruid; 438 439 old_ruid = new_ruid = current->uid; 440 old_suid = current->suid; 441 if (capable(CAP_SETUID)) 442 new_ruid = current->euid = current->suid = current->fsuid = uid; 443 else if ((uid == current->uid) || (uid == current->suid)) 444 current->fsuid = current->euid = uid; 445 else 446 return -EPERM; 447 448 if (current->euid != old_euid) 449 current->dumpable = 0; 450 451 if (new_ruid != old_ruid) { 452 /* See comment above about NPROC rlimit issues... */ 453 free_uid(current); 454 current->uid = new_ruid; 455 alloc_uid(current); 456 } 457 458 if (!issecure(SECURE_NO_SETUID_FIXUP)) { 459 cap_emulate_setxuid(old_ruid, old_euid, old_suid); 460 } 461 462 return 0; 463 } 464 465 466 /* 467 * This function implements a generic ability to update ruid, euid, 468 * and suid. This allows you to implement the 4.4 compatible seteuid(). 469 */ 470 asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) 471 { 472 int old_ruid = current->uid; 473 int old_euid = current->euid; 474 int old_suid = current->suid; 475 476 if (!capable(CAP_SETUID)) { 477 if ((ruid != (uid_t) -1) && (ruid != current->uid) && 478 (ruid != current->euid) && (ruid != current->suid)) 479 return -EPERM; 480 if ((euid != (uid_t) -1) && (euid != current->uid) && 481 (euid != current->euid) && (euid != current->suid)) 482 return -EPERM; 483 if ((suid != (uid_t) -1) && (suid != current->uid) && 484 (suid != current->euid) && (suid != current->suid)) 485 return -EPERM; 486 } 487 if (ruid != (uid_t) -1) { 488 /* See above commentary about NPROC rlimit issues here. */ 489 free_uid(current); 490 current->uid = ruid; 491 alloc_uid(current); 492 } 493 if (euid != (uid_t) -1) { 494 if (euid != current->euid) 495 current->dumpable = 0; 496 current->euid = euid; 497 current->fsuid = euid; 498 } 499 if (suid != (uid_t) -1) 500 current->suid = suid; 501 502 if (!issecure(SECURE_NO_SETUID_FIXUP)) { 503 cap_emulate_setxuid(old_ruid, old_euid, old_suid); 504 } 505 506 return 0; 507 } 508 509 asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) 510 { 511 int retval; 512 513 if (!(retval = put_user(current->uid, ruid)) && 514 !(retval = put_user(current->euid, euid))) 515 retval = put_user(current->suid, suid); 516 517 return retval; 518 } 519 520 /* 521 * Same as above, but for rgid, egid, sgid. 522 */ 523 asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) 524 { 525 if (!capable(CAP_SETGID)) { 526 if ((rgid != (gid_t) -1) && (rgid != current->gid) && 527 (rgid != current->egid) && (rgid != current->sgid)) 528 return -EPERM; 529 if ((egid != (gid_t) -1) && (egid != current->gid) && 530 (egid != current->egid) && (egid != current->sgid)) 531 return -EPERM; 532 if ((sgid != (gid_t) -1) && (sgid != current->gid) && 533 (sgid != current->egid) && (sgid != current->sgid)) 534 return -EPERM; 535 } 536 if (rgid != (gid_t) -1) 537 current->gid = rgid; 538 if (egid != (gid_t) -1) { 539 if (egid != current->egid) 540 current->dumpable = 0; 541 current->egid = egid; 542 current->fsgid = egid; 543 } 544 if (sgid != (gid_t) -1) 545 current->sgid = sgid; 546 return 0; 547 } 548 549 asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) 550 { 551 int retval; 552 553 if (!(retval = put_user(current->gid, rgid)) && 554 !(retval = put_user(current->egid, egid))) 555 retval = put_user(current->sgid, sgid); 556 557 return retval; 558 } 559 560 561 /* 562 * "setfsuid()" sets the fsuid - the uid used for filesystem checks. This 563 * is used for "access()" and for the NFS daemon (letting nfsd stay at 564 * whatever uid it wants to). It normally shadows "euid", except when 565 * explicitly set by setfsuid() or for access.. 566 */ 567 asmlinkage long sys_setfsuid(uid_t uid) 568 { 569 int old_fsuid; 570 571 old_fsuid = current->fsuid; 572 if (uid == current->uid || uid == current->euid || 573 uid == current->suid || uid == current->fsuid || 574 capable(CAP_SETUID)) 575 current->fsuid = uid; 576 if (current->fsuid != old_fsuid) 577 current->dumpable = 0; 578 579 /* We emulate fsuid by essentially doing a scaled-down version 580 * of what we did in setresuid and friends. However, we only 581 * operate on the fs-specific bits of the process' effective 582 * capabilities 583 * 584 * FIXME - is fsuser used for all CAP_FS_MASK capabilities? 585 * if not, we might be a bit too harsh here. 586 */ 587 588 if (!issecure(SECURE_NO_SETUID_FIXUP)) { 589 if (old_fsuid == 0 && current->fsuid != 0) { 590 cap_t(current->cap_effective) &= ~CAP_FS_MASK; 591 } 592 if (old_fsuid != 0 && current->fsuid == 0) { 593 cap_t(current->cap_effective) |= 594 (cap_t(current->cap_permitted) & CAP_FS_MASK); 595 } 596 } 597 598 return old_fsuid; 599 } 600 601 /* 602 * Samma på svenska.. 603 */ 604 asmlinkage long sys_setfsgid(gid_t gid) 605 { 606 int old_fsgid; 607 608 old_fsgid = current->fsgid; 609 if (gid == current->gid || gid == current->egid || 610 gid == current->sgid || gid == current->fsgid || 611 capable(CAP_SETGID)) 612 current->fsgid = gid; 613 if (current->fsgid != old_fsgid) 614 current->dumpable = 0; 615 616 return old_fsgid; 617 } 618 619 asmlinkage long sys_times(struct tms * tbuf) 620 { 621 /* 622 * In the SMP world we might just be unlucky and have one of 623 * the times increment as we use it. Since the value is an 624 * atomically safe type this is just fine. Conceptually its 625 * as if the syscall took an instant longer to occur. 626 */ 627 if (tbuf) 628 if (copy_to_user(tbuf, &current->times, sizeof(struct tms))) 629 return -EFAULT; 630 return jiffies; 631 } 632 633 /* 634 * This needs some heavy checking ... 635 * I just haven't the stomach for it. I also don't fully 636 * understand sessions/pgrp etc. Let somebody who does explain it. 637 * 638 * OK, I think I have the protection semantics right.... this is really 639 * only important on a multi-user system anyway, to make sure one user 640 * can't send a signal to a process owned by another. -TYT, 12/12/91 641 * 642 * Auch. Had to add the 'did_exec' flag to conform completely to POSIX. 643 * LBT 04.03.94 644 */ 645 646 asmlinkage long sys_setpgid(pid_t pid, pid_t pgid) 647 { 648 struct task_struct * p; 649 int err = -EINVAL; 650 651 if (!pid) 652 pid = current->pid; 653 if (!pgid) 654 pgid = pid; 655 if (pgid < 0) 656 return -EINVAL; 657 658 /* From this point forward we keep holding onto the tasklist lock 659 * so that our parent does not change from under us. -DaveM 660 */ 661 read_lock(&tasklist_lock); 662 663 err = -ESRCH; 664 p = find_task_by_pid(pid); 665 if (!p) 666 goto out; 667 668 if (p->p_pptr == current || p->p_opptr == current) { 669 err = -EPERM; 670 if (p->session != current->session) 671 goto out; 672 err = -EACCES; 673 if (p->did_exec) 674 goto out; 675 } else if (p != current) 676 goto out; 677 err = -EPERM; 678 if (p->leader) 679 goto out; 680 if (pgid != pid) { 681 struct task_struct * tmp; 682 for_each_task (tmp) { 683 if (tmp->pgrp == pgid && 684 tmp->session == current->session) 685 goto ok_pgid; 686 } 687 goto out; 688 } 689 690 ok_pgid: 691 p->pgrp = pgid; 692 err = 0; 693 out: 694 /* All paths lead to here, thus we are safe. -DaveM */ 695 read_unlock(&tasklist_lock); 696 return err; 697 } 698 699 asmlinkage long sys_getpgid(pid_t pid) 700 { 701 if (!pid) { 702 return current->pgrp; 703 } else { 704 int retval; 705 struct task_struct *p; 706 707 read_lock(&tasklist_lock); 708 p = find_task_by_pid(pid); 709 710 retval = -ESRCH; 711 if (p) 712 retval = p->pgrp; 713 read_unlock(&tasklist_lock); 714 return retval; 715 } 716 } 717 718 asmlinkage long sys_getpgrp(void) 719 { 720 /* SMP - assuming writes are word atomic this is fine */ 721 return current->pgrp; 722 } 723 724 asmlinkage long sys_getsid(pid_t pid) 725 { 726 if (!pid) { 727 return current->session; 728 } else { 729 int retval; 730 struct task_struct *p; 731 732 read_lock(&tasklist_lock); 733 p = find_task_by_pid(pid); 734 735 retval = -ESRCH; 736 if(p) 737 retval = p->session; 738 read_unlock(&tasklist_lock); 739 return retval; 740 } 741 } 742 743 asmlinkage long sys_setsid(void) 744 { 745 struct task_struct * p; 746 int err = -EPERM; 747 748 read_lock(&tasklist_lock); 749 for_each_task(p) { 750 if (p->pgrp == current->pid) 751 goto out; 752 } 753 754 current->leader = 1; 755 current->session = current->pgrp = current->pid; 756 current->tty = NULL; 757 current->tty_old_pgrp = 0; 758 err = current->pgrp; 759 out: 760 read_unlock(&tasklist_lock); 761 return err; 762 } 763 764 /* 765 * Supplementary group IDs 766 */ 767 asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist) 768 { 769 int i; 770 771 /* 772 * SMP: Nobody else can change our grouplist. Thus we are 773 * safe. 774 */ 775 776 if (gidsetsize < 0) 777 return -EINVAL; 778 i = current->ngroups; 779 if (gidsetsize) { 780 if (i > gidsetsize) 781 return -EINVAL; 782 if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i)) 783 return -EFAULT; 784 } 785 return i; 786 } 787 788 /* 789 * SMP: Our groups are not shared. We can copy to/from them safely 790 * without another task interfering. 791 */ 792 793 asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist) 794 { 795 if (!capable(CAP_SETGID)) 796 return -EPERM; 797 if ((unsigned) gidsetsize > NGROUPS) 798 return -EINVAL; 799 if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t))) 800 return -EFAULT; 801 current->ngroups = gidsetsize; 802 return 0; 803 } 804 805 int in_group_p(gid_t grp) 806 { 807 if (grp != current->fsgid) { 808 int i = current->ngroups; 809 if (i) { 810 gid_t *groups = current->groups; 811 do { 812 if (*groups == grp) 813 goto out; 814 groups++; 815 i--; 816 } while (i); 817 } 818 return 0; 819 } 820 out: 821 return 1; 822 } 823 824 /* Like in_group_p, but testing against egid, not fsgid */ 825 int in_egroup_p(gid_t grp) 826 { 827 if (grp != current->egid) { 828 int i = current->ngroups; 829 if (i) { 830 gid_t *groups = current->groups; 831 do { 832 if (*groups == grp) 833 goto out; 834 groups++; 835 i--; 836 } while (i); 837 } 838 return 0; 839 } 840 out: 841 return 1; 842 } 843 844 DECLARE_RWSEM(uts_sem); 845 846 asmlinkage long sys_newuname(struct new_utsname * name) 847 { 848 int errno = 0; 849 850 down_read(&uts_sem); 851 if (copy_to_user(name,&system_utsname,sizeof *name)) 852 errno = -EFAULT; 853 up_read(&uts_sem); 854 return errno; 855 } 856 857 asmlinkage long sys_sethostname(char *name, int len) 858 { 859 int errno; 860 861 if (!capable(CAP_SYS_ADMIN)) 862 return -EPERM; 863 if (len < 0 || len > __NEW_UTS_LEN) 864 return -EINVAL; 865 down_write(&uts_sem); 866 errno = -EFAULT; 867 if (!copy_from_user(system_utsname.nodename, name, len)) { 868 system_utsname.nodename[len] = 0; 869 errno = 0; 870 } 871 up_write(&uts_sem); 872 return errno; 873 } 874 875 asmlinkage long sys_gethostname(char *name, int len) 876 { 877 int i, errno; 878 879 if (len < 0) 880 return -EINVAL; 881 down_read(&uts_sem); 882 i = 1 + strlen(system_utsname.nodename); 883 if (i > len) 884 i = len; 885 errno = 0; 886 if (copy_to_user(name, system_utsname.nodename, i)) 887 errno = -EFAULT; 888 up_read(&uts_sem); 889 return errno; 890 } 891 892 /* 893 * Only setdomainname; getdomainname can be implemented by calling 894 * uname() 895 */ 896 asmlinkage long sys_setdomainname(char *name, int len) 897 { 898 int errno; 899 900 if (!capable(CAP_SYS_ADMIN)) 901 return -EPERM; 902 if (len < 0 || len > __NEW_UTS_LEN) 903 return -EINVAL; 904 905 down_write(&uts_sem); 906 errno = -EFAULT; 907 if (!copy_from_user(system_utsname.domainname, name, len)) { 908 errno = 0; 909 system_utsname.domainname[len] = 0; 910 } 911 up_write(&uts_sem); 912 return errno; 913 } 914 915 asmlinkage long sys_getrlimit(unsigned int resource, struct rlimit *rlim) 916 { 917 if (resource >= RLIM_NLIMITS) 918 return -EINVAL; 919 else 920 return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim)) 921 ? -EFAULT : 0; 922 } 923 924 #if !defined(__ia64__) 925 926 /* 927 * Back compatibility for getrlimit. Needed for some apps. 928 */ 929 930 asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim) 931 { 932 struct rlimit x; 933 if (resource >= RLIM_NLIMITS) 934 return -EINVAL; 935 936 memcpy(&x, current->rlim + resource, sizeof(*rlim)); 937 if(x.rlim_cur > 0x7FFFFFFF) 938 x.rlim_cur = 0x7FFFFFFF; 939 if(x.rlim_max > 0x7FFFFFFF) 940 x.rlim_max = 0x7FFFFFFF; 941 return copy_to_user(rlim, &x, sizeof(x))?-EFAULT:0; 942 } 943 944 #endif 945 946 asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim) 947 { 948 struct rlimit new_rlim, *old_rlim; 949 950 if (resource >= RLIM_NLIMITS) 951 return -EINVAL; 952 if(copy_from_user(&new_rlim, rlim, sizeof(*rlim))) 953 return -EFAULT; 954 if (new_rlim.rlim_cur < 0 || new_rlim.rlim_max < 0) 955 return -EINVAL; 956 old_rlim = current->rlim + resource; 957 if (((new_rlim.rlim_cur > old_rlim->rlim_max) || 958 (new_rlim.rlim_max > old_rlim->rlim_max)) && 959 !capable(CAP_SYS_RESOURCE)) 960 return -EPERM; 961 if (resource == RLIMIT_NOFILE) { 962 if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN) 963 return -EPERM; 964 } 965 *old_rlim = new_rlim; 966 return 0; 967 } 968 969 /* 970 * It would make sense to put struct rusage in the task_struct, 971 * except that would make the task_struct be *really big*. After 972 * task_struct gets moved into malloc'ed memory, it would 973 * make sense to do this. It will make moving the rest of the information 974 * a lot simpler! (Which we're not doing right now because we're not 975 * measuring them yet). 976 * 977 * This is SMP safe. Either we are called from sys_getrusage on ourselves 978 * below (we know we aren't going to exit/disappear and only we change our 979 * rusage counters), or we are called from wait4() on a process which is 980 * either stopped or zombied. In the zombied case the task won't get 981 * reaped till shortly after the call to getrusage(), in both cases the 982 * task being examined is in a frozen state so the counters won't change. 983 * 984 * FIXME! Get the fault counts properly! 985 */ 986 int getrusage(struct task_struct *p, int who, struct rusage *ru) 987 { 988 struct rusage r; 989 990 memset((char *) &r, 0, sizeof(r)); 991 switch (who) { 992 case RUSAGE_SELF: 993 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime); 994 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime); 995 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime); 996 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime); 997 r.ru_minflt = p->min_flt; 998 r.ru_majflt = p->maj_flt; 999 r.ru_nswap = p->nswap; 1000 break; 1001 case RUSAGE_CHILDREN: 1002 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_cutime); 1003 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_cutime); 1004 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_cstime); 1005 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_cstime); 1006 r.ru_minflt = p->cmin_flt; 1007 r.ru_majflt = p->cmaj_flt; 1008 r.ru_nswap = p->cnswap; 1009 break; 1010 default: 1011 r.ru_utime.tv_sec = CT_TO_SECS(p->times.tms_utime + p->times.tms_cutime); 1012 r.ru_utime.tv_usec = CT_TO_USECS(p->times.tms_utime + p->times.tms_cutime); 1013 r.ru_stime.tv_sec = CT_TO_SECS(p->times.tms_stime + p->times.tms_cstime); 1014 r.ru_stime.tv_usec = CT_TO_USECS(p->times.tms_stime + p->times.tms_cstime); 1015 r.ru_minflt = p->min_flt + p->cmin_flt; 1016 r.ru_majflt = p->maj_flt + p->cmaj_flt; 1017 r.ru_nswap = p->nswap + p->cnswap; 1018 break; 1019 } 1020 return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0; 1021 } 1022 1023 asmlinkage long sys_getrusage(int who, struct rusage *ru) 1024 { 1025 if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN) 1026 return -EINVAL; 1027 return getrusage(current, who, ru); 1028 } 1029 1030 asmlinkage long sys_umask(int mask) 1031 { 1032 mask = xchg(&current->fs->umask, mask & S_IRWXUGO); 1033 return mask; 1034 } 1035 1036 asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, 1037 unsigned long arg4, unsigned long arg5) 1038 { 1039 int error = 0; 1040 int sig; 1041 1042 switch (option) { 1043 case PR_SET_PDEATHSIG: 1044 sig = arg2; 1045 if (sig > _NSIG) { 1046 error = -EINVAL; 1047 break; 1048 } 1049 current->pdeath_signal = sig; 1050 break; 1051 case PR_GET_PDEATHSIG: 1052 error = put_user(current->pdeath_signal, (int *)arg2); 1053 break; 1054 case PR_GET_DUMPABLE: 1055 if (current->dumpable) 1056 error = 1; 1057 break; 1058 case PR_SET_DUMPABLE: 1059 if (arg2 != 0 && arg2 != 1) { 1060 error = -EINVAL; 1061 break; 1062 } 1063 current->dumpable = arg2; 1064 break; 1065 default: 1066 error = -EINVAL; 1067 break; 1068 } 1069 return error; 1070 } 1071 1072

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.