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