1 /* 2 * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 39 * $FreeBSD: src/sys/kern/kern_prot.c,v 1.53.2.9 2002/03/09 05:20:26 dd Exp $ 40 */ 41 42 /* 43 * System calls related to processes and protection 44 */ 45 46 #include "opt_compat.h" 47 48 #include <sys/param.h> 49 #include <sys/acct.h> 50 #include <sys/systm.h> 51 #include <sys/sysproto.h> 52 #include <sys/kernel.h> 53 #include <sys/proc.h> 54 #include <sys/malloc.h> 55 #include <sys/pioctl.h> 56 #include <sys/resourcevar.h> 57 58 static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 59 60 #ifndef _SYS_SYSPROTO_H_ 61 struct getpid_args { 62 int dummy; 63 }; 64 #endif 65 66 /* 67 * NOT MP SAFE due to p_pptr access 68 */ 69 /* ARGSUSED */ 70 int 71 getpid(p, uap) 72 struct proc *p; 73 struct getpid_args *uap; 74 { 75 76 p->p_retval[0] = p->p_pid; 77 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 78 p->p_retval[1] = p->p_pptr->p_pid; 79 #endif 80 return (0); 81 } 82 83 #ifndef _SYS_SYSPROTO_H_ 84 struct getppid_args { 85 int dummy; 86 }; 87 #endif 88 /* ARGSUSED */ 89 int 90 getppid(p, uap) 91 struct proc *p; 92 struct getppid_args *uap; 93 { 94 95 p->p_retval[0] = p->p_pptr->p_pid; 96 return (0); 97 } 98 99 /* 100 * Get process group ID; note that POSIX getpgrp takes no parameter 101 * 102 * MP SAFE 103 */ 104 #ifndef _SYS_SYSPROTO_H_ 105 struct getpgrp_args { 106 int dummy; 107 }; 108 #endif 109 110 int 111 getpgrp(p, uap) 112 struct proc *p; 113 struct getpgrp_args *uap; 114 { 115 116 p->p_retval[0] = p->p_pgrp->pg_id; 117 return (0); 118 } 119 120 /* Get an arbitary pid's process group id */ 121 #ifndef _SYS_SYSPROTO_H_ 122 struct getpgid_args { 123 pid_t pid; 124 }; 125 #endif 126 127 int 128 getpgid(p, uap) 129 struct proc *p; 130 struct getpgid_args *uap; 131 { 132 struct proc *pt; 133 134 pt = p; 135 if (uap->pid == 0) 136 goto found; 137 138 if ((pt = pfind(uap->pid)) == 0) 139 return ESRCH; 140 found: 141 p->p_retval[0] = pt->p_pgrp->pg_id; 142 return 0; 143 } 144 145 /* 146 * Get an arbitary pid's session id. 147 */ 148 #ifndef _SYS_SYSPROTO_H_ 149 struct getsid_args { 150 pid_t pid; 151 }; 152 #endif 153 154 int 155 getsid(p, uap) 156 struct proc *p; 157 struct getsid_args *uap; 158 { 159 struct proc *pt; 160 161 pt = p; 162 if (uap->pid == 0) 163 goto found; 164 165 if ((pt = pfind(uap->pid)) == 0) 166 return ESRCH; 167 found: 168 p->p_retval[0] = pt->p_session->s_sid; 169 return 0; 170 } 171 172 173 /* 174 * getuid() - MP SAFE 175 */ 176 #ifndef _SYS_SYSPROTO_H_ 177 struct getuid_args { 178 int dummy; 179 }; 180 #endif 181 182 /* ARGSUSED */ 183 int 184 getuid(p, uap) 185 struct proc *p; 186 struct getuid_args *uap; 187 { 188 189 p->p_retval[0] = p->p_cred->p_ruid; 190 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 191 p->p_retval[1] = p->p_ucred->cr_uid; 192 #endif 193 return (0); 194 } 195 196 /* 197 * geteuid() - MP SAFE 198 */ 199 #ifndef _SYS_SYSPROTO_H_ 200 struct geteuid_args { 201 int dummy; 202 }; 203 #endif 204 205 /* ARGSUSED */ 206 int 207 geteuid(p, uap) 208 struct proc *p; 209 struct geteuid_args *uap; 210 { 211 212 p->p_retval[0] = p->p_ucred->cr_uid; 213 return (0); 214 } 215 216 /* 217 * getgid() - MP SAFE 218 */ 219 #ifndef _SYS_SYSPROTO_H_ 220 struct getgid_args { 221 int dummy; 222 }; 223 #endif 224 225 /* ARGSUSED */ 226 int 227 getgid(p, uap) 228 struct proc *p; 229 struct getgid_args *uap; 230 { 231 232 p->p_retval[0] = p->p_cred->p_rgid; 233 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 234 p->p_retval[1] = p->p_ucred->cr_groups[0]; 235 #endif 236 return (0); 237 } 238 239 /* 240 * Get effective group ID. The "egid" is groups[0], and could be obtained 241 * via getgroups. This syscall exists because it is somewhat painful to do 242 * correctly in a library function. 243 */ 244 #ifndef _SYS_SYSPROTO_H_ 245 struct getegid_args { 246 int dummy; 247 }; 248 #endif 249 250 /* ARGSUSED */ 251 int 252 getegid(p, uap) 253 struct proc *p; 254 struct getegid_args *uap; 255 { 256 257 p->p_retval[0] = p->p_ucred->cr_groups[0]; 258 return (0); 259 } 260 261 #ifndef _SYS_SYSPROTO_H_ 262 struct getgroups_args { 263 u_int gidsetsize; 264 gid_t *gidset; 265 }; 266 #endif 267 int 268 getgroups(p, uap) 269 struct proc *p; 270 register struct getgroups_args *uap; 271 { 272 register struct pcred *pc = p->p_cred; 273 register u_int ngrp; 274 int error; 275 276 if ((ngrp = uap->gidsetsize) == 0) { 277 p->p_retval[0] = pc->pc_ucred->cr_ngroups; 278 return (0); 279 } 280 if (ngrp < pc->pc_ucred->cr_ngroups) 281 return (EINVAL); 282 ngrp = pc->pc_ucred->cr_ngroups; 283 if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, 284 (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 285 return (error); 286 p->p_retval[0] = ngrp; 287 return (0); 288 } 289 290 #ifndef _SYS_SYSPROTO_H_ 291 struct setsid_args { 292 int dummy; 293 }; 294 #endif 295 296 /* ARGSUSED */ 297 int 298 setsid(p, uap) 299 register struct proc *p; 300 struct setsid_args *uap; 301 { 302 303 if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 304 return (EPERM); 305 } else { 306 (void)enterpgrp(p, p->p_pid, 1); 307 p->p_retval[0] = p->p_pid; 308 return (0); 309 } 310 } 311 312 /* 313 * set process group (setpgid/old setpgrp) 314 * 315 * caller does setpgid(targpid, targpgid) 316 * 317 * pid must be caller or child of caller (ESRCH) 318 * if a child 319 * pid must be in same session (EPERM) 320 * pid can't have done an exec (EACCES) 321 * if pgid != pid 322 * there must exist some pid in same session having pgid (EPERM) 323 * pid must not be session leader (EPERM) 324 */ 325 #ifndef _SYS_SYSPROTO_H_ 326 struct setpgid_args { 327 int pid; /* target process id */ 328 int pgid; /* target pgrp id */ 329 }; 330 #endif 331 /* ARGSUSED */ 332 int 333 setpgid(curp, uap) 334 struct proc *curp; 335 register struct setpgid_args *uap; 336 { 337 register struct proc *targp; /* target process */ 338 register struct pgrp *pgrp; /* target pgrp */ 339 340 if (uap->pgid < 0) 341 return (EINVAL); 342 if (uap->pid != 0 && uap->pid != curp->p_pid) { 343 if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) 344 return (ESRCH); 345 if (targp->p_pgrp == NULL || targp->p_session != curp->p_session) 346 return (EPERM); 347 if (targp->p_flag & P_EXEC) 348 return (EACCES); 349 } else 350 targp = curp; 351 if (SESS_LEADER(targp)) 352 return (EPERM); 353 if (uap->pgid == 0) 354 uap->pgid = targp->p_pid; 355 else if (uap->pgid != targp->p_pid) 356 if ((pgrp = pgfind(uap->pgid)) == 0 || 357 pgrp->pg_session != curp->p_session) 358 return (EPERM); 359 return (enterpgrp(targp, uap->pgid, 0)); 360 } 361 362 /* 363 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 364 * compatable. It says that setting the uid/gid to euid/egid is a special 365 * case of "appropriate privilege". Once the rules are expanded out, this 366 * basically means that setuid(nnn) sets all three id's, in all permitted 367 * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 368 * does not set the saved id - this is dangerous for traditional BSD 369 * programs. For this reason, we *really* do not want to set 370 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 371 */ 372 #define POSIX_APPENDIX_B_4_2_2 373 374 #ifndef _SYS_SYSPROTO_H_ 375 struct setuid_args { 376 uid_t uid; 377 }; 378 #endif 379 /* ARGSUSED */ 380 int 381 setuid(p, uap) 382 struct proc *p; 383 struct setuid_args *uap; 384 { 385 register struct pcred *pc = p->p_cred; 386 register uid_t uid; 387 int error; 388 389 /* 390 * See if we have "permission" by POSIX 1003.1 rules. 391 * 392 * Note that setuid(geteuid()) is a special case of 393 * "appropriate privileges" in appendix B.4.2.2. We need 394 * to use this clause to be compatable with traditional BSD 395 * semantics. Basically, it means that "setuid(xx)" sets all 396 * three id's (assuming you have privs). 397 * 398 * Notes on the logic. We do things in three steps. 399 * 1: We determine if the euid is going to change, and do EPERM 400 * right away. We unconditionally change the euid later if this 401 * test is satisfied, simplifying that part of the logic. 402 * 2: We determine if the real and/or saved uid's are going to 403 * change. Determined by compile options. 404 * 3: Change euid last. (after tests in #2 for "appropriate privs") 405 */ 406 uid = uap->uid; 407 if (uid != pc->p_ruid && /* allow setuid(getuid()) */ 408 #ifdef _POSIX_SAVED_IDS 409 uid != pc->p_svuid && /* allow setuid(saved gid) */ 410 #endif 411 #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 412 uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ 413 #endif 414 (error = suser_xxx(0, p, PRISON_ROOT))) 415 return (error); 416 417 #ifdef _POSIX_SAVED_IDS 418 /* 419 * Do we have "appropriate privileges" (are we root or uid == euid) 420 * If so, we are changing the real uid and/or saved uid. 421 */ 422 if ( 423 #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 424 uid == pc->pc_ucred->cr_uid || 425 #endif 426 suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 427 #endif 428 { 429 /* 430 * Set the real uid and transfer proc count to new user. 431 */ 432 if (uid != pc->p_ruid) { 433 change_ruid(p, uid); 434 setsugid(p); 435 } 436 /* 437 * Set saved uid 438 * 439 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 440 * the security of seteuid() depends on it. B.4.2.2 says it 441 * is important that we should do this. 442 */ 443 if (pc->p_svuid != uid) { 444 pc->p_svuid = uid; 445 setsugid(p); 446 } 447 } 448 449 /* 450 * In all permitted cases, we are changing the euid. 451 * Copy credentials so other references do not see our changes. 452 */ 453 if (pc->pc_ucred->cr_uid != uid) { 454 change_euid(p, uid); 455 setsugid(p); 456 } 457 return (0); 458 } 459 460 #ifndef _SYS_SYSPROTO_H_ 461 struct seteuid_args { 462 uid_t euid; 463 }; 464 #endif 465 /* ARGSUSED */ 466 int 467 seteuid(p, uap) 468 struct proc *p; 469 struct seteuid_args *uap; 470 { 471 register struct pcred *pc = p->p_cred; 472 register uid_t euid; 473 int error; 474 475 euid = uap->euid; 476 if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ 477 euid != pc->p_svuid && /* allow seteuid(saved uid) */ 478 (error = suser_xxx(0, p, PRISON_ROOT))) 479 return (error); 480 /* 481 * Everything's okay, do it. Copy credentials so other references do 482 * not see our changes. 483 */ 484 if (pc->pc_ucred->cr_uid != euid) { 485 change_euid(p, euid); 486 setsugid(p); 487 } 488 return (0); 489 } 490 491 #ifndef _SYS_SYSPROTO_H_ 492 struct setgid_args { 493 gid_t gid; 494 }; 495 #endif 496 /* ARGSUSED */ 497 int 498 setgid(p, uap) 499 struct proc *p; 500 struct setgid_args *uap; 501 { 502 register struct pcred *pc = p->p_cred; 503 register gid_t gid; 504 int error; 505 506 /* 507 * See if we have "permission" by POSIX 1003.1 rules. 508 * 509 * Note that setgid(getegid()) is a special case of 510 * "appropriate privileges" in appendix B.4.2.2. We need 511 * to use this clause to be compatable with traditional BSD 512 * semantics. Basically, it means that "setgid(xx)" sets all 513 * three id's (assuming you have privs). 514 * 515 * For notes on the logic here, see setuid() above. 516 */ 517 gid = uap->gid; 518 if (gid != pc->p_rgid && /* allow setgid(getgid()) */ 519 #ifdef _POSIX_SAVED_IDS 520 gid != pc->p_svgid && /* allow setgid(saved gid) */ 521 #endif 522 #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 523 gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ 524 #endif 525 (error = suser_xxx(0, p, PRISON_ROOT))) 526 return (error); 527 528 #ifdef _POSIX_SAVED_IDS 529 /* 530 * Do we have "appropriate privileges" (are we root or gid == egid) 531 * If so, we are changing the real uid and saved gid. 532 */ 533 if ( 534 #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 535 gid == pc->pc_ucred->cr_groups[0] || 536 #endif 537 suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 538 #endif 539 { 540 /* 541 * Set real gid 542 */ 543 if (pc->p_rgid != gid) { 544 pc->p_rgid = gid; 545 setsugid(p); 546 } 547 /* 548 * Set saved gid 549 * 550 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 551 * the security of setegid() depends on it. B.4.2.2 says it 552 * is important that we should do this. 553 */ 554 if (pc->p_svgid != gid) { 555 pc->p_svgid = gid; 556 setsugid(p); 557 } 558 } 559 /* 560 * In all cases permitted cases, we are changing the egid. 561 * Copy credentials so other references do not see our changes. 562 */ 563 if (pc->pc_ucred->cr_groups[0] != gid) { 564 pc->pc_ucred = crcopy(pc->pc_ucred); 565 pc->pc_ucred->cr_groups[0] = gid; 566 setsugid(p); 567 } 568 return (0); 569 } 570 571 #ifndef _SYS_SYSPROTO_H_ 572 struct setegid_args { 573 gid_t egid; 574 }; 575 #endif 576 /* ARGSUSED */ 577 int 578 setegid(p, uap) 579 struct proc *p; 580 struct setegid_args *uap; 581 { 582 register struct pcred *pc = p->p_cred; 583 register gid_t egid; 584 int error; 585 586 egid = uap->egid; 587 if (egid != pc->p_rgid && /* allow setegid(getgid()) */ 588 egid != pc->p_svgid && /* allow setegid(saved gid) */ 589 (error = suser_xxx(0, p, PRISON_ROOT))) 590 return (error); 591 if (pc->pc_ucred->cr_groups[0] != egid) { 592 pc->pc_ucred = crcopy(pc->pc_ucred); 593 pc->pc_ucred->cr_groups[0] = egid; 594 setsugid(p); 595 } 596 return (0); 597 } 598 599 #ifndef _SYS_SYSPROTO_H_ 600 struct setgroups_args { 601 u_int gidsetsize; 602 gid_t *gidset; 603 }; 604 #endif 605 /* ARGSUSED */ 606 int 607 setgroups(p, uap) 608 struct proc *p; 609 struct setgroups_args *uap; 610 { 611 register struct pcred *pc = p->p_cred; 612 register u_int ngrp; 613 int error; 614 615 if ((error = suser_xxx(0, p, PRISON_ROOT))) 616 return (error); 617 ngrp = uap->gidsetsize; 618 if (ngrp > NGROUPS) 619 return (EINVAL); 620 /* 621 * XXX A little bit lazy here. We could test if anything has 622 * changed before crcopy() and setting P_SUGID. 623 */ 624 pc->pc_ucred = crcopy(pc->pc_ucred); 625 if (ngrp < 1) { 626 /* 627 * setgroups(0, NULL) is a legitimate way of clearing the 628 * groups vector on non-BSD systems (which generally do not 629 * have the egid in the groups[0]). We risk security holes 630 * when running non-BSD software if we do not do the same. 631 */ 632 pc->pc_ucred->cr_ngroups = 1; 633 } else { 634 if ((error = copyin((caddr_t)uap->gidset, 635 (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) 636 return (error); 637 pc->pc_ucred->cr_ngroups = ngrp; 638 } 639 setsugid(p); 640 return (0); 641 } 642 643 #ifndef _SYS_SYSPROTO_H_ 644 struct setreuid_args { 645 uid_t ruid; 646 uid_t euid; 647 }; 648 #endif 649 /* ARGSUSED */ 650 int 651 setreuid(p, uap) 652 register struct proc *p; 653 struct setreuid_args *uap; 654 { 655 register struct pcred *pc = p->p_cred; 656 register uid_t ruid, euid; 657 int error; 658 659 ruid = uap->ruid; 660 euid = uap->euid; 661 if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) || 662 (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && 663 euid != pc->p_ruid && euid != pc->p_svuid)) && 664 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 665 return (error); 666 667 if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 668 change_euid(p, euid); 669 setsugid(p); 670 } 671 if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 672 change_ruid(p, ruid); 673 setsugid(p); 674 } 675 if ((ruid != (uid_t)-1 || pc->pc_ucred->cr_uid != pc->p_ruid) && 676 pc->p_svuid != pc->pc_ucred->cr_uid) { 677 pc->p_svuid = pc->pc_ucred->cr_uid; 678 setsugid(p); 679 } 680 return (0); 681 } 682 683 #ifndef _SYS_SYSPROTO_H_ 684 struct setregid_args { 685 gid_t rgid; 686 gid_t egid; 687 }; 688 #endif 689 /* ARGSUSED */ 690 int 691 setregid(p, uap) 692 register struct proc *p; 693 struct setregid_args *uap; 694 { 695 register struct pcred *pc = p->p_cred; 696 register gid_t rgid, egid; 697 int error; 698 699 rgid = uap->rgid; 700 egid = uap->egid; 701 if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) || 702 (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] && 703 egid != pc->p_rgid && egid != pc->p_svgid)) && 704 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 705 return (error); 706 707 if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 708 pc->pc_ucred = crcopy(pc->pc_ucred); 709 pc->pc_ucred->cr_groups[0] = egid; 710 setsugid(p); 711 } 712 if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 713 pc->p_rgid = rgid; 714 setsugid(p); 715 } 716 if ((rgid != (gid_t)-1 || pc->pc_ucred->cr_groups[0] != pc->p_rgid) && 717 pc->p_svgid != pc->pc_ucred->cr_groups[0]) { 718 pc->p_svgid = pc->pc_ucred->cr_groups[0]; 719 setsugid(p); 720 } 721 return (0); 722 } 723 724 /* 725 * setresuid(ruid, euid, suid) is like setreuid except control over the 726 * saved uid is explicit. 727 */ 728 729 #ifndef _SYS_SYSPROTO_H_ 730 struct setresuid_args { 731 uid_t ruid; 732 uid_t euid; 733 uid_t suid; 734 }; 735 #endif 736 /* ARGSUSED */ 737 int 738 setresuid(p, uap) 739 register struct proc *p; 740 struct setresuid_args *uap; 741 { 742 register struct pcred *pc = p->p_cred; 743 register uid_t ruid, euid, suid; 744 int error; 745 746 ruid = uap->ruid; 747 euid = uap->euid; 748 suid = uap->suid; 749 if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid && 750 ruid != pc->pc_ucred->cr_uid) || 751 (euid != (uid_t)-1 && euid != pc->p_ruid && euid != pc->p_svuid && 752 euid != pc->pc_ucred->cr_uid) || 753 (suid != (uid_t)-1 && suid != pc->p_ruid && suid != pc->p_svuid && 754 suid != pc->pc_ucred->cr_uid)) && 755 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 756 return (error); 757 if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 758 change_euid(p, euid); 759 setsugid(p); 760 } 761 if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 762 change_ruid(p, ruid); 763 setsugid(p); 764 } 765 if (suid != (uid_t)-1 && pc->p_svuid != suid) { 766 pc->p_svuid = suid; 767 setsugid(p); 768 } 769 return (0); 770 } 771 772 /* 773 * setresgid(rgid, egid, sgid) is like setregid except control over the 774 * saved gid is explicit. 775 */ 776 777 #ifndef _SYS_SYSPROTO_H_ 778 struct setresgid_args { 779 gid_t rgid; 780 gid_t egid; 781 gid_t sgid; 782 }; 783 #endif 784 /* ARGSUSED */ 785 int 786 setresgid(p, uap) 787 register struct proc *p; 788 struct setresgid_args *uap; 789 { 790 register struct pcred *pc = p->p_cred; 791 register gid_t rgid, egid, sgid; 792 int error; 793 794 rgid = uap->rgid; 795 egid = uap->egid; 796 sgid = uap->sgid; 797 if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid && 798 rgid != pc->pc_ucred->cr_groups[0]) || 799 (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid && 800 egid != pc->pc_ucred->cr_groups[0]) || 801 (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid && 802 sgid != pc->pc_ucred->cr_groups[0])) && 803 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 804 return (error); 805 806 if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 807 pc->pc_ucred = crcopy(pc->pc_ucred); 808 pc->pc_ucred->cr_groups[0] = egid; 809 setsugid(p); 810 } 811 if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 812 pc->p_rgid = rgid; 813 setsugid(p); 814 } 815 if (sgid != (gid_t)-1 && pc->p_svgid != sgid) { 816 pc->p_svgid = sgid; 817 setsugid(p); 818 } 819 return (0); 820 } 821 822 #ifndef _SYS_SYSPROTO_H_ 823 struct getresuid_args { 824 uid_t *ruid; 825 uid_t *euid; 826 uid_t *suid; 827 }; 828 #endif 829 /* ARGSUSED */ 830 int 831 getresuid(p, uap) 832 register struct proc *p; 833 struct getresuid_args *uap; 834 { 835 struct pcred *pc = p->p_cred; 836 int error1 = 0, error2 = 0, error3 = 0; 837 838 if (uap->ruid) 839 error1 = copyout((caddr_t)&pc->p_ruid, 840 (caddr_t)uap->ruid, sizeof(pc->p_ruid)); 841 if (uap->euid) 842 error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid, 843 (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid)); 844 if (uap->suid) 845 error3 = copyout((caddr_t)&pc->p_svuid, 846 (caddr_t)uap->suid, sizeof(pc->p_svuid)); 847 return error1 ? error1 : (error2 ? error2 : error3); 848 } 849 850 #ifndef _SYS_SYSPROTO_H_ 851 struct getresgid_args { 852 gid_t *rgid; 853 gid_t *egid; 854 gid_t *sgid; 855 }; 856 #endif 857 /* ARGSUSED */ 858 int 859 getresgid(p, uap) 860 register struct proc *p; 861 struct getresgid_args *uap; 862 { 863 struct pcred *pc = p->p_cred; 864 int error1 = 0, error2 = 0, error3 = 0; 865 866 if (uap->rgid) 867 error1 = copyout((caddr_t)&pc->p_rgid, 868 (caddr_t)uap->rgid, sizeof(pc->p_rgid)); 869 if (uap->egid) 870 error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0], 871 (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0])); 872 if (uap->sgid) 873 error3 = copyout((caddr_t)&pc->p_svgid, 874 (caddr_t)uap->sgid, sizeof(pc->p_svgid)); 875 return error1 ? error1 : (error2 ? error2 : error3); 876 } 877 878 879 #ifndef _SYS_SYSPROTO_H_ 880 struct issetugid_args { 881 int dummy; 882 }; 883 #endif 884 /* ARGSUSED */ 885 int 886 issetugid(p, uap) 887 register struct proc *p; 888 struct issetugid_args *uap; 889 { 890 /* 891 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 892 * we use P_SUGID because we consider changing the owners as 893 * "tainting" as well. 894 * This is significant for procs that start as root and "become" 895 * a user without an exec - programs cannot know *everything* 896 * that libc *might* have put in their data segment. 897 */ 898 p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 899 return (0); 900 } 901 902 /* 903 * Check if gid is a member of the group set. 904 */ 905 int 906 groupmember(gid, cred) 907 gid_t gid; 908 register struct ucred *cred; 909 { 910 register gid_t *gp; 911 gid_t *egp; 912 913 egp = &(cred->cr_groups[cred->cr_ngroups]); 914 for (gp = cred->cr_groups; gp < egp; gp++) 915 if (*gp == gid) 916 return (1); 917 return (0); 918 } 919 920 /* 921 * Test whether the specified credentials imply "super-user" 922 * privilege; if so, and we have accounting info, set the flag 923 * indicating use of super-powers. 924 * Returns 0 or error. 925 */ 926 int 927 suser(p) 928 struct proc *p; 929 { 930 return suser_xxx(0, p, 0); 931 } 932 933 int 934 suser_xxx(cred, proc, flag) 935 struct ucred *cred; 936 struct proc *proc; 937 int flag; 938 { 939 if (!cred && !proc) { 940 printf("suser_xxx(): THINK!\n"); 941 return (EPERM); 942 } 943 if (!cred) 944 cred = proc->p_ucred; 945 if (cred->cr_uid != 0) 946 return (EPERM); 947 if (proc && proc->p_prison && !(flag & PRISON_ROOT)) 948 return (EPERM); 949 if (proc) 950 proc->p_acflag |= ASU; 951 return (0); 952 } 953 954 /* 955 * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise. 956 */ 957 958 int 959 p_trespass(struct proc *p1, struct proc *p2) 960 { 961 962 if (p1 == p2) 963 return (0); 964 if (!PRISON_CHECK(p1, p2)) 965 return (ESRCH); 966 if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) 967 return (0); 968 if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid) 969 return (0); 970 if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid) 971 return (0); 972 if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid) 973 return (0); 974 if (!suser_xxx(0, p1, PRISON_ROOT)) 975 return (0); 976 return (EPERM); 977 } 978 979 /* 980 * Allocate a zeroed cred structure. 981 */ 982 struct ucred * 983 crget() 984 { 985 register struct ucred *cr; 986 987 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 988 bzero((caddr_t)cr, sizeof(*cr)); 989 cr->cr_ref = 1; 990 return (cr); 991 } 992 993 /* 994 * Claim another reference to a ucred structure 995 */ 996 void 997 crhold(cr) 998 struct ucred *cr; 999 { 1000 cr->cr_ref++; 1001 } 1002 1003 /* 1004 * Free a cred structure. 1005 * Throws away space when ref count gets to 0. 1006 */ 1007 void 1008 crfree(cr) 1009 struct ucred *cr; 1010 { 1011 if (cr->cr_ref == 0) 1012 panic("Freeing already free credential! %p", cr); 1013 1014 if (--cr->cr_ref == 0) { 1015 /* 1016 * Some callers of crget(), such as nfs_statfs(), 1017 * allocate a temporary credential, but don't 1018 * allocate a uidinfo structure. 1019 */ 1020 if (cr->cr_uidinfo != NULL) 1021 uifree(cr->cr_uidinfo); 1022 FREE((caddr_t)cr, M_CRED); 1023 } 1024 } 1025 1026 /* 1027 * Copy cred structure to a new one and free the old one. 1028 */ 1029 struct ucred * 1030 crcopy(cr) 1031 struct ucred *cr; 1032 { 1033 struct ucred *newcr; 1034 1035 if (cr->cr_ref == 1) 1036 return (cr); 1037 newcr = crget(); 1038 *newcr = *cr; 1039 uihold(newcr->cr_uidinfo); 1040 crfree(cr); 1041 newcr->cr_ref = 1; 1042 return (newcr); 1043 } 1044 1045 /* 1046 * Dup cred struct to a new held one. 1047 */ 1048 struct ucred * 1049 crdup(cr) 1050 struct ucred *cr; 1051 { 1052 struct ucred *newcr; 1053 1054 newcr = crget(); 1055 *newcr = *cr; 1056 uihold(newcr->cr_uidinfo); 1057 newcr->cr_ref = 1; 1058 return (newcr); 1059 } 1060 1061 /* 1062 * Fill in a struct xucred based on a struct ucred. 1063 */ 1064 void 1065 cru2x(cr, xcr) 1066 struct ucred *cr; 1067 struct xucred *xcr; 1068 { 1069 1070 bzero(xcr, sizeof(*xcr)); 1071 xcr->cr_version = XUCRED_VERSION; 1072 xcr->cr_uid = cr->cr_uid; 1073 xcr->cr_ngroups = cr->cr_ngroups; 1074 bcopy(cr->cr_groups, xcr->cr_groups, sizeof(cr->cr_groups)); 1075 } 1076 1077 /* 1078 * Get login name, if available. 1079 */ 1080 #ifndef _SYS_SYSPROTO_H_ 1081 struct getlogin_args { 1082 char *namebuf; 1083 u_int namelen; 1084 }; 1085 #endif 1086 /* ARGSUSED */ 1087 int 1088 getlogin(p, uap) 1089 struct proc *p; 1090 struct getlogin_args *uap; 1091 { 1092 1093 if (uap->namelen > MAXLOGNAME) 1094 uap->namelen = MAXLOGNAME; 1095 return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 1096 (caddr_t) uap->namebuf, uap->namelen)); 1097 } 1098 1099 /* 1100 * Set login name. 1101 */ 1102 #ifndef _SYS_SYSPROTO_H_ 1103 struct setlogin_args { 1104 char *namebuf; 1105 }; 1106 #endif 1107 /* ARGSUSED */ 1108 int 1109 setlogin(p, uap) 1110 struct proc *p; 1111 struct setlogin_args *uap; 1112 { 1113 int error; 1114 char logintmp[MAXLOGNAME]; 1115 1116 if ((error = suser_xxx(0, p, PRISON_ROOT))) 1117 return (error); 1118 error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 1119 sizeof(logintmp), (size_t *)0); 1120 if (error == ENAMETOOLONG) 1121 error = EINVAL; 1122 else if (!error) 1123 (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 1124 sizeof(logintmp)); 1125 return (error); 1126 } 1127 1128 void 1129 setsugid(p) 1130 struct proc *p; 1131 { 1132 p->p_flag |= P_SUGID; 1133 if (!(p->p_pfsflags & PF_ISUGID)) 1134 p->p_stops = 0; 1135 } 1136 1137 /* 1138 * Helper function to change the effective uid of a process 1139 */ 1140 void 1141 change_euid(p, euid) 1142 struct proc *p; 1143 uid_t euid; 1144 { 1145 struct pcred *pc; 1146 struct uidinfo *uip; 1147 1148 pc = p->p_cred; 1149 /* 1150 * crcopy is essentially a NOP if ucred has a reference count 1151 * of 1, which is true if it has already been copied. 1152 */ 1153 pc->pc_ucred = crcopy(pc->pc_ucred); 1154 uip = pc->pc_ucred->cr_uidinfo; 1155 pc->pc_ucred->cr_uid = euid; 1156 pc->pc_ucred->cr_uidinfo = uifind(euid); 1157 uifree(uip); 1158 } 1159 1160 /* 1161 * Helper function to change the real uid of a process 1162 * 1163 * The per-uid process count for this process is transfered from 1164 * the old uid to the new uid. 1165 */ 1166 void 1167 change_ruid(p, ruid) 1168 struct proc *p; 1169 uid_t ruid; 1170 { 1171 struct pcred *pc; 1172 struct uidinfo *uip; 1173 1174 pc = p->p_cred; 1175 (void)chgproccnt(pc->p_uidinfo, -1, 0); 1176 uip = pc->p_uidinfo; 1177 /* It is assumed that pcred is not shared between processes */ 1178 pc->p_ruid = ruid; 1179 pc->p_uidinfo = uifind(ruid); 1180 (void)chgproccnt(pc->p_uidinfo, 1, 0); 1181 uifree(uip); 1182 } 1183