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