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