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