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