kern_prot.c revision 72786
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: head/sys/kern/kern_prot.c 72786 2001-02-21 06:39:57Z rwatson $ 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/lock.h> 54#include <sys/proc.h> 55#include <sys/malloc.h> 56#include <sys/pioctl.h> 57#include <sys/resourcevar.h> 58#include <sys/sysctl.h> 59#include <sys/jail.h> 60 61static MALLOC_DEFINE(M_CRED, "cred", "credentials"); 62 63#ifndef _SYS_SYSPROTO_H_ 64struct getpid_args { 65 int dummy; 66}; 67#endif 68 69/* 70 * getpid - MP SAFE 71 */ 72 73/* ARGSUSED */ 74int 75getpid(p, uap) 76 struct proc *p; 77 struct getpid_args *uap; 78{ 79 80 p->p_retval[0] = p->p_pid; 81#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 82 PROCTREE_LOCK(PT_SHARED); 83 p->p_retval[1] = p->p_pptr->p_pid; 84 PROCTREE_LOCK(PT_RELEASE); 85#endif 86 return (0); 87} 88 89/* 90 * getppid - MP SAFE 91 */ 92 93#ifndef _SYS_SYSPROTO_H_ 94struct getppid_args { 95 int dummy; 96}; 97#endif 98/* ARGSUSED */ 99int 100getppid(p, uap) 101 struct proc *p; 102 struct getppid_args *uap; 103{ 104 105 PROCTREE_LOCK(PT_SHARED); 106 p->p_retval[0] = p->p_pptr->p_pid; 107 PROCTREE_LOCK(PT_RELEASE); 108 return (0); 109} 110 111/* 112 * Get process group ID; note that POSIX getpgrp takes no parameter 113 * 114 * MP SAFE 115 */ 116#ifndef _SYS_SYSPROTO_H_ 117struct getpgrp_args { 118 int dummy; 119}; 120#endif 121 122int 123getpgrp(p, uap) 124 struct proc *p; 125 struct getpgrp_args *uap; 126{ 127 128 p->p_retval[0] = p->p_pgrp->pg_id; 129 return (0); 130} 131 132/* Get an arbitary pid's process group id */ 133#ifndef _SYS_SYSPROTO_H_ 134struct getpgid_args { 135 pid_t pid; 136}; 137#endif 138 139int 140getpgid(p, uap) 141 struct proc *p; 142 struct getpgid_args *uap; 143{ 144 struct proc *pt; 145 146 pt = p; 147 if (uap->pid == 0) 148 goto found; 149 150 if ((pt = pfind(uap->pid)) == 0) 151 return ESRCH; 152found: 153 p->p_retval[0] = pt->p_pgrp->pg_id; 154 return 0; 155} 156 157/* 158 * Get an arbitary pid's session id. 159 */ 160#ifndef _SYS_SYSPROTO_H_ 161struct getsid_args { 162 pid_t pid; 163}; 164#endif 165 166int 167getsid(p, uap) 168 struct proc *p; 169 struct getsid_args *uap; 170{ 171 struct proc *pt; 172 173 pt = p; 174 if (uap->pid == 0) 175 goto found; 176 177 if ((pt = pfind(uap->pid)) == 0) 178 return ESRCH; 179found: 180 p->p_retval[0] = pt->p_session->s_sid; 181 return 0; 182} 183 184 185/* 186 * getuid() - MP SAFE 187 */ 188#ifndef _SYS_SYSPROTO_H_ 189struct getuid_args { 190 int dummy; 191}; 192#endif 193 194/* ARGSUSED */ 195int 196getuid(p, uap) 197 struct proc *p; 198 struct getuid_args *uap; 199{ 200 201 p->p_retval[0] = p->p_cred->p_ruid; 202#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 203 p->p_retval[1] = p->p_ucred->cr_uid; 204#endif 205 return (0); 206} 207 208/* 209 * geteuid() - MP SAFE 210 */ 211#ifndef _SYS_SYSPROTO_H_ 212struct geteuid_args { 213 int dummy; 214}; 215#endif 216 217/* ARGSUSED */ 218int 219geteuid(p, uap) 220 struct proc *p; 221 struct geteuid_args *uap; 222{ 223 224 p->p_retval[0] = p->p_ucred->cr_uid; 225 return (0); 226} 227 228/* 229 * getgid() - MP SAFE 230 */ 231#ifndef _SYS_SYSPROTO_H_ 232struct getgid_args { 233 int dummy; 234}; 235#endif 236 237/* ARGSUSED */ 238int 239getgid(p, uap) 240 struct proc *p; 241 struct getgid_args *uap; 242{ 243 244 p->p_retval[0] = p->p_cred->p_rgid; 245#if defined(COMPAT_43) || defined(COMPAT_SUNOS) 246 p->p_retval[1] = p->p_ucred->cr_groups[0]; 247#endif 248 return (0); 249} 250 251/* 252 * Get effective group ID. The "egid" is groups[0], and could be obtained 253 * via getgroups. This syscall exists because it is somewhat painful to do 254 * correctly in a library function. 255 */ 256#ifndef _SYS_SYSPROTO_H_ 257struct getegid_args { 258 int dummy; 259}; 260#endif 261 262/* ARGSUSED */ 263int 264getegid(p, uap) 265 struct proc *p; 266 struct getegid_args *uap; 267{ 268 269 p->p_retval[0] = p->p_ucred->cr_groups[0]; 270 return (0); 271} 272 273#ifndef _SYS_SYSPROTO_H_ 274struct getgroups_args { 275 u_int gidsetsize; 276 gid_t *gidset; 277}; 278#endif 279int 280getgroups(p, uap) 281 struct proc *p; 282 register struct getgroups_args *uap; 283{ 284 register struct pcred *pc = p->p_cred; 285 register u_int ngrp; 286 int error; 287 288 if ((ngrp = uap->gidsetsize) == 0) { 289 p->p_retval[0] = pc->pc_ucred->cr_ngroups; 290 return (0); 291 } 292 if (ngrp < pc->pc_ucred->cr_ngroups) 293 return (EINVAL); 294 ngrp = pc->pc_ucred->cr_ngroups; 295 if ((error = copyout((caddr_t)pc->pc_ucred->cr_groups, 296 (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) 297 return (error); 298 p->p_retval[0] = ngrp; 299 return (0); 300} 301 302#ifndef _SYS_SYSPROTO_H_ 303struct setsid_args { 304 int dummy; 305}; 306#endif 307 308/* ARGSUSED */ 309int 310setsid(p, uap) 311 register struct proc *p; 312 struct setsid_args *uap; 313{ 314 315 if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) { 316 return (EPERM); 317 } else { 318 (void)enterpgrp(p, p->p_pid, 1); 319 p->p_retval[0] = p->p_pid; 320 return (0); 321 } 322} 323 324/* 325 * set process group (setpgid/old setpgrp) 326 * 327 * caller does setpgid(targpid, targpgid) 328 * 329 * pid must be caller or child of caller (ESRCH) 330 * if a child 331 * pid must be in same session (EPERM) 332 * pid can't have done an exec (EACCES) 333 * if pgid != pid 334 * there must exist some pid in same session having pgid (EPERM) 335 * pid must not be session leader (EPERM) 336 */ 337#ifndef _SYS_SYSPROTO_H_ 338struct setpgid_args { 339 int pid; /* target process id */ 340 int pgid; /* target pgrp id */ 341}; 342#endif 343/* ARGSUSED */ 344int 345setpgid(curp, uap) 346 struct proc *curp; 347 register struct setpgid_args *uap; 348{ 349 register struct proc *targp; /* target process */ 350 register struct pgrp *pgrp; /* target pgrp */ 351 352 if (uap->pgid < 0) 353 return (EINVAL); 354 if (uap->pid != 0 && uap->pid != curp->p_pid) { 355 if ((targp = pfind(uap->pid)) == 0 || !inferior(targp)) 356 return (ESRCH); 357 if (targp->p_pgrp == NULL || targp->p_session != curp->p_session) 358 return (EPERM); 359 if (targp->p_flag & P_EXEC) 360 return (EACCES); 361 } else 362 targp = curp; 363 if (SESS_LEADER(targp)) 364 return (EPERM); 365 if (uap->pgid == 0) 366 uap->pgid = targp->p_pid; 367 else if (uap->pgid != targp->p_pid) 368 if ((pgrp = pgfind(uap->pgid)) == 0 || 369 pgrp->pg_session != curp->p_session) 370 return (EPERM); 371 return (enterpgrp(targp, uap->pgid, 0)); 372} 373 374/* 375 * Use the clause in B.4.2.2 that allows setuid/setgid to be 4.2/4.3BSD 376 * compatible. It says that setting the uid/gid to euid/egid is a special 377 * case of "appropriate privilege". Once the rules are expanded out, this 378 * basically means that setuid(nnn) sets all three id's, in all permitted 379 * cases unless _POSIX_SAVED_IDS is enabled. In that case, setuid(getuid()) 380 * does not set the saved id - this is dangerous for traditional BSD 381 * programs. For this reason, we *really* do not want to set 382 * _POSIX_SAVED_IDS and do not want to clear POSIX_APPENDIX_B_4_2_2. 383 */ 384#define POSIX_APPENDIX_B_4_2_2 385 386#ifndef _SYS_SYSPROTO_H_ 387struct setuid_args { 388 uid_t uid; 389}; 390#endif 391/* ARGSUSED */ 392int 393setuid(p, uap) 394 struct proc *p; 395 struct setuid_args *uap; 396{ 397 register struct pcred *pc = p->p_cred; 398 register uid_t uid; 399 int error; 400 401 /* 402 * See if we have "permission" by POSIX 1003.1 rules. 403 * 404 * Note that setuid(geteuid()) is a special case of 405 * "appropriate privileges" in appendix B.4.2.2. We need 406 * to use this clause to be compatible with traditional BSD 407 * semantics. Basically, it means that "setuid(xx)" sets all 408 * three id's (assuming you have privs). 409 * 410 * Notes on the logic. We do things in three steps. 411 * 1: We determine if the euid is going to change, and do EPERM 412 * right away. We unconditionally change the euid later if this 413 * test is satisfied, simplifying that part of the logic. 414 * 2: We determine if the real and/or saved uid's are going to 415 * change. Determined by compile options. 416 * 3: Change euid last. (after tests in #2 for "appropriate privs") 417 */ 418 uid = uap->uid; 419 if (uid != pc->p_ruid && /* allow setuid(getuid()) */ 420#ifdef _POSIX_SAVED_IDS 421 uid != pc->p_svuid && /* allow setuid(saved gid) */ 422#endif 423#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 424 uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ 425#endif 426 (error = suser_xxx(0, p, PRISON_ROOT))) 427 return (error); 428 429#ifdef _POSIX_SAVED_IDS 430 /* 431 * Do we have "appropriate privileges" (are we root or uid == euid) 432 * If so, we are changing the real uid and/or saved uid. 433 */ 434 if ( 435#ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ 436 uid == pc->pc_ucred->cr_uid || 437#endif 438 suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 439#endif 440 { 441 /* 442 * Set the real uid and transfer proc count to new user. 443 */ 444 if (uid != pc->p_ruid) { 445 change_ruid(p, uid); 446 setsugid(p); 447 } 448 /* 449 * Set saved uid 450 * 451 * XXX always set saved uid even if not _POSIX_SAVED_IDS, as 452 * the security of seteuid() depends on it. B.4.2.2 says it 453 * is important that we should do this. 454 */ 455 if (pc->p_svuid != uid) { 456 pc->p_svuid = uid; 457 setsugid(p); 458 } 459 } 460 461 /* 462 * In all permitted cases, we are changing the euid. 463 * Copy credentials so other references do not see our changes. 464 */ 465 if (pc->pc_ucred->cr_uid != uid) { 466 change_euid(p, uid); 467 setsugid(p); 468 } 469 return (0); 470} 471 472#ifndef _SYS_SYSPROTO_H_ 473struct seteuid_args { 474 uid_t euid; 475}; 476#endif 477/* ARGSUSED */ 478int 479seteuid(p, uap) 480 struct proc *p; 481 struct seteuid_args *uap; 482{ 483 register struct pcred *pc = p->p_cred; 484 register uid_t euid; 485 int error; 486 487 euid = uap->euid; 488 if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ 489 euid != pc->p_svuid && /* allow seteuid(saved uid) */ 490 (error = suser_xxx(0, p, PRISON_ROOT))) 491 return (error); 492 /* 493 * Everything's okay, do it. Copy credentials so other references do 494 * not see our changes. 495 */ 496 if (pc->pc_ucred->cr_uid != euid) { 497 change_euid(p, euid); 498 setsugid(p); 499 } 500 return (0); 501} 502 503#ifndef _SYS_SYSPROTO_H_ 504struct setgid_args { 505 gid_t gid; 506}; 507#endif 508/* ARGSUSED */ 509int 510setgid(p, uap) 511 struct proc *p; 512 struct setgid_args *uap; 513{ 514 register struct pcred *pc = p->p_cred; 515 register gid_t gid; 516 int error; 517 518 /* 519 * See if we have "permission" by POSIX 1003.1 rules. 520 * 521 * Note that setgid(getegid()) is a special case of 522 * "appropriate privileges" in appendix B.4.2.2. We need 523 * to use this clause to be compatible with traditional BSD 524 * semantics. Basically, it means that "setgid(xx)" sets all 525 * three id's (assuming you have privs). 526 * 527 * For notes on the logic here, see setuid() above. 528 */ 529 gid = uap->gid; 530 if (gid != pc->p_rgid && /* allow setgid(getgid()) */ 531#ifdef _POSIX_SAVED_IDS 532 gid != pc->p_svgid && /* allow setgid(saved gid) */ 533#endif 534#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ 535 gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ 536#endif 537 (error = suser_xxx(0, p, PRISON_ROOT))) 538 return (error); 539 540#ifdef _POSIX_SAVED_IDS 541 /* 542 * Do we have "appropriate privileges" (are we root or gid == egid) 543 * If so, we are changing the real uid and saved gid. 544 */ 545 if ( 546#ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ 547 gid == pc->pc_ucred->cr_groups[0] || 548#endif 549 suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ 550#endif 551 { 552 /* 553 * Set real gid 554 */ 555 if (pc->p_rgid != gid) { 556 pc->p_rgid = gid; 557 setsugid(p); 558 } 559 /* 560 * Set saved gid 561 * 562 * XXX always set saved gid even if not _POSIX_SAVED_IDS, as 563 * the security of setegid() depends on it. B.4.2.2 says it 564 * is important that we should do this. 565 */ 566 if (pc->p_svgid != gid) { 567 pc->p_svgid = gid; 568 setsugid(p); 569 } 570 } 571 /* 572 * In all cases permitted cases, we are changing the egid. 573 * Copy credentials so other references do not see our changes. 574 */ 575 if (pc->pc_ucred->cr_groups[0] != gid) { 576 pc->pc_ucred = crcopy(pc->pc_ucred); 577 pc->pc_ucred->cr_groups[0] = gid; 578 setsugid(p); 579 } 580 return (0); 581} 582 583#ifndef _SYS_SYSPROTO_H_ 584struct setegid_args { 585 gid_t egid; 586}; 587#endif 588/* ARGSUSED */ 589int 590setegid(p, uap) 591 struct proc *p; 592 struct setegid_args *uap; 593{ 594 register struct pcred *pc = p->p_cred; 595 register gid_t egid; 596 int error; 597 598 egid = uap->egid; 599 if (egid != pc->p_rgid && /* allow setegid(getgid()) */ 600 egid != pc->p_svgid && /* allow setegid(saved gid) */ 601 (error = suser_xxx(0, p, PRISON_ROOT))) 602 return (error); 603 if (pc->pc_ucred->cr_groups[0] != egid) { 604 pc->pc_ucred = crcopy(pc->pc_ucred); 605 pc->pc_ucred->cr_groups[0] = egid; 606 setsugid(p); 607 } 608 return (0); 609} 610 611#ifndef _SYS_SYSPROTO_H_ 612struct setgroups_args { 613 u_int gidsetsize; 614 gid_t *gidset; 615}; 616#endif 617/* ARGSUSED */ 618int 619setgroups(p, uap) 620 struct proc *p; 621 struct setgroups_args *uap; 622{ 623 register struct pcred *pc = p->p_cred; 624 register u_int ngrp; 625 int error; 626 627 if ((error = suser_xxx(0, p, PRISON_ROOT))) 628 return (error); 629 ngrp = uap->gidsetsize; 630 if (ngrp > NGROUPS) 631 return (EINVAL); 632 /* 633 * XXX A little bit lazy here. We could test if anything has 634 * changed before crcopy() and setting P_SUGID. 635 */ 636 pc->pc_ucred = crcopy(pc->pc_ucred); 637 if (ngrp < 1) { 638 /* 639 * setgroups(0, NULL) is a legitimate way of clearing the 640 * groups vector on non-BSD systems (which generally do not 641 * have the egid in the groups[0]). We risk security holes 642 * when running non-BSD software if we do not do the same. 643 */ 644 pc->pc_ucred->cr_ngroups = 1; 645 } else { 646 if ((error = copyin((caddr_t)uap->gidset, 647 (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))) 648 return (error); 649 pc->pc_ucred->cr_ngroups = ngrp; 650 } 651 setsugid(p); 652 return (0); 653} 654 655#ifndef _SYS_SYSPROTO_H_ 656struct setreuid_args { 657 uid_t ruid; 658 uid_t euid; 659}; 660#endif 661/* ARGSUSED */ 662int 663setreuid(p, uap) 664 register struct proc *p; 665 struct setreuid_args *uap; 666{ 667 register struct pcred *pc = p->p_cred; 668 register uid_t ruid, euid; 669 int error; 670 671 ruid = uap->ruid; 672 euid = uap->euid; 673 if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) || 674 (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && 675 euid != pc->p_ruid && euid != pc->p_svuid)) && 676 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 677 return (error); 678 679 if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { 680 change_euid(p, euid); 681 setsugid(p); 682 } 683 if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 684 change_ruid(p, 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_ 696struct setregid_args { 697 gid_t rgid; 698 gid_t egid; 699}; 700#endif 701/* ARGSUSED */ 702int 703setregid(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_ 742struct setresuid_args { 743 uid_t ruid; 744 uid_t euid; 745 uid_t suid; 746}; 747#endif 748/* ARGSUSED */ 749int 750setresuid(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 change_euid(p, euid); 771 setsugid(p); 772 } 773 if (ruid != (uid_t)-1 && pc->p_ruid != ruid) { 774 change_ruid(p, ruid); 775 setsugid(p); 776 } 777 if (suid != (uid_t)-1 && pc->p_svuid != suid) { 778 pc->p_svuid = suid; 779 setsugid(p); 780 } 781 return (0); 782} 783 784/* 785 * setresgid(rgid, egid, sgid) is like setregid except control over the 786 * saved gid is explicit. 787 */ 788 789#ifndef _SYS_SYSPROTO_H_ 790struct setresgid_args { 791 gid_t rgid; 792 gid_t egid; 793 gid_t sgid; 794}; 795#endif 796/* ARGSUSED */ 797int 798setresgid(p, uap) 799 register struct proc *p; 800 struct setresgid_args *uap; 801{ 802 register struct pcred *pc = p->p_cred; 803 register gid_t rgid, egid, sgid; 804 int error; 805 806 rgid = uap->rgid; 807 egid = uap->egid; 808 sgid = uap->sgid; 809 if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid && 810 rgid != pc->pc_ucred->cr_groups[0]) || 811 (egid != (gid_t)-1 && egid != pc->p_rgid && egid != pc->p_svgid && 812 egid != pc->pc_ucred->cr_groups[0]) || 813 (sgid != (gid_t)-1 && sgid != pc->p_rgid && sgid != pc->p_svgid && 814 sgid != pc->pc_ucred->cr_groups[0])) && 815 (error = suser_xxx(0, p, PRISON_ROOT)) != 0) 816 return (error); 817 818 if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { 819 pc->pc_ucred = crcopy(pc->pc_ucred); 820 pc->pc_ucred->cr_groups[0] = egid; 821 setsugid(p); 822 } 823 if (rgid != (gid_t)-1 && pc->p_rgid != rgid) { 824 pc->p_rgid = rgid; 825 setsugid(p); 826 } 827 if (sgid != (gid_t)-1 && pc->p_svgid != sgid) { 828 pc->p_svgid = sgid; 829 setsugid(p); 830 } 831 return (0); 832} 833 834#ifndef _SYS_SYSPROTO_H_ 835struct getresuid_args { 836 uid_t *ruid; 837 uid_t *euid; 838 uid_t *suid; 839}; 840#endif 841/* ARGSUSED */ 842int 843getresuid(p, uap) 844 register struct proc *p; 845 struct getresuid_args *uap; 846{ 847 struct pcred *pc = p->p_cred; 848 int error1 = 0, error2 = 0, error3 = 0; 849 850 if (uap->ruid) 851 error1 = copyout((caddr_t)&pc->p_ruid, 852 (caddr_t)uap->ruid, sizeof(pc->p_ruid)); 853 if (uap->euid) 854 error2 = copyout((caddr_t)&pc->pc_ucred->cr_uid, 855 (caddr_t)uap->euid, sizeof(pc->pc_ucred->cr_uid)); 856 if (uap->suid) 857 error3 = copyout((caddr_t)&pc->p_svuid, 858 (caddr_t)uap->suid, sizeof(pc->p_svuid)); 859 return error1 ? error1 : (error2 ? error2 : error3); 860} 861 862#ifndef _SYS_SYSPROTO_H_ 863struct getresgid_args { 864 gid_t *rgid; 865 gid_t *egid; 866 gid_t *sgid; 867}; 868#endif 869/* ARGSUSED */ 870int 871getresgid(p, uap) 872 register struct proc *p; 873 struct getresgid_args *uap; 874{ 875 struct pcred *pc = p->p_cred; 876 int error1 = 0, error2 = 0, error3 = 0; 877 878 if (uap->rgid) 879 error1 = copyout((caddr_t)&pc->p_rgid, 880 (caddr_t)uap->rgid, sizeof(pc->p_rgid)); 881 if (uap->egid) 882 error2 = copyout((caddr_t)&pc->pc_ucred->cr_groups[0], 883 (caddr_t)uap->egid, sizeof(pc->pc_ucred->cr_groups[0])); 884 if (uap->sgid) 885 error3 = copyout((caddr_t)&pc->p_svgid, 886 (caddr_t)uap->sgid, sizeof(pc->p_svgid)); 887 return error1 ? error1 : (error2 ? error2 : error3); 888} 889 890 891#ifndef _SYS_SYSPROTO_H_ 892struct issetugid_args { 893 int dummy; 894}; 895#endif 896/* ARGSUSED */ 897int 898issetugid(p, uap) 899 register struct proc *p; 900 struct issetugid_args *uap; 901{ 902 /* 903 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time, 904 * we use P_SUGID because we consider changing the owners as 905 * "tainting" as well. 906 * This is significant for procs that start as root and "become" 907 * a user without an exec - programs cannot know *everything* 908 * that libc *might* have put in their data segment. 909 */ 910 p->p_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0; 911 return (0); 912} 913 914/* 915 * Check if gid is a member of the group set. 916 */ 917int 918groupmember(gid, cred) 919 gid_t gid; 920 register struct ucred *cred; 921{ 922 register gid_t *gp; 923 gid_t *egp; 924 925 egp = &(cred->cr_groups[cred->cr_ngroups]); 926 for (gp = cred->cr_groups; gp < egp; gp++) 927 if (*gp == gid) 928 return (1); 929 return (0); 930} 931 932static int suser_permitted = 1; 933 934SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0, 935 "processes with uid 0 have privilege"); 936 937/* 938 * Test whether the specified credentials imply "super-user" 939 * privilege; if so, and we have accounting info, set the flag 940 * indicating use of super-powers. 941 * Returns 0 or error. 942 */ 943int 944suser(p) 945 struct proc *p; 946{ 947 return suser_xxx(0, p, 0); 948} 949 950int 951suser_xxx(cred, proc, flag) 952 struct ucred *cred; 953 struct proc *proc; 954 int flag; 955{ 956 if (!suser_permitted) 957 return (EPERM); 958 if (!cred && !proc) { 959 printf("suser_xxx(): THINK!\n"); 960 return (EPERM); 961 } 962 if (!cred) 963 cred = proc->p_ucred; 964 if (cred->cr_uid != 0) 965 return (EPERM); 966 if (jailed(cred) && !(flag & PRISON_ROOT)) 967 return (EPERM); 968 return (0); 969} 970 971static int 972p_cansee(struct proc *p1, struct proc *p2, int *privused) 973{ 974 int error; 975 976 if (privused != NULL) 977 *privused = 0; 978 979 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 980 return (error); 981 982 if (!ps_showallprocs && p1->p_ucred->cr_uid != p2->p_ucred->cr_uid) { 983 if (suser_xxx(NULL, p1, PRISON_ROOT) == 0) { 984 if (privused != NULL) 985 *privused = 1; 986 return (0); 987 } 988 return (ESRCH); 989 } 990 991 return (0); 992} 993 994static int 995p_cankill(struct proc *p1, struct proc *p2, int *privused) 996{ 997 int error; 998 999 if (privused != NULL) 1000 *privused = 0; 1001 1002 if (p1 == p2) 1003 return (0); 1004 1005 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 1006 return (error); 1007 1008 if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) 1009 return (0); 1010 if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid) 1011 return (0); 1012 /* 1013 * XXX should a process be able to affect another process 1014 * acting as the same uid (i.e., a userland nfsd or the like?) 1015 */ 1016 if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid) 1017 return (0); 1018 if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid) 1019 return (0); 1020 1021 if (!suser_xxx(0, p1, PRISON_ROOT)) { 1022 if (privused != NULL) 1023 *privused = 1; 1024 return (0); 1025 } 1026 1027#ifdef CAPABILITIES 1028 if (!cap_check_xxx(0, p1, CAP_KILL, PRISON_ROOT)) { 1029 if (privused != NULL) 1030 *privused = 1; 1031 return (0); 1032 } 1033#endif 1034 1035 return (EPERM); 1036} 1037 1038static int 1039p_cansched(struct proc *p1, struct proc *p2, int *privused) 1040{ 1041 int error; 1042 1043 if (privused != NULL) 1044 *privused = 0; 1045 1046 if (p1 == p2) 1047 return (0); 1048 1049 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 1050 return (error); 1051 1052 if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) 1053 return (0); 1054 if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid) 1055 return (0); 1056 /* 1057 * XXX should a process be able to affect another process 1058 * acting as the same uid (i.e., a userland nfsd or the like?) 1059 */ 1060 if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid) 1061 return (0); 1062 if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid) 1063 return (0); 1064 1065 if (!suser_xxx(0, p1, PRISON_ROOT)) { 1066 if (privused != NULL) 1067 *privused = 1; 1068 return (0); 1069 } 1070 1071#ifdef CAPABILITIES 1072 if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) { 1073 if (privused != NULL) 1074 *privused = 1; 1075 return (0); 1076 } 1077#endif 1078 1079 return (EPERM); 1080} 1081 1082static int 1083p_candebug(struct proc *p1, struct proc *p2, int *privused) 1084{ 1085 int error; 1086 1087 if (privused != NULL) 1088 *privused = 0; 1089 1090 /* XXX it is authorized, but semantics don't permit it */ 1091 if (p1 == p2) 1092 return (0); 1093 1094 if ((error = prison_check(p1->p_ucred, p2->p_ucred))) 1095 return (error); 1096 1097 /* not owned by you, has done setuid (unless you're root) */ 1098 /* add a CAP_SYS_PTRACE here? */ 1099 if (p1->p_cred->pc_ucred->cr_uid != p2->p_cred->p_ruid || 1100 p1->p_cred->p_ruid != p2->p_cred->p_ruid || 1101 p1->p_cred->p_svuid != p2->p_cred->p_ruid || 1102 p2->p_flag & P_SUGID) { 1103 if ((error = suser_xxx(0, p1, PRISON_ROOT))) 1104 return (error); 1105 if (privused != NULL) 1106 *privused = 1; 1107 } 1108 1109 /* can't trace init when securelevel > 0 */ 1110 if (securelevel > 0 && p2->p_pid == 1) 1111 return (EPERM); 1112 1113 return (0); 1114} 1115 1116int 1117p_can(struct proc *p1, struct proc *p2, int operation, 1118 int *privused) 1119{ 1120 1121 switch(operation) { 1122 case P_CAN_SEE: 1123 return (p_cansee(p1, p2, privused)); 1124 1125 case P_CAN_KILL: 1126 return (p_cankill(p1, p2, privused)); 1127 1128 case P_CAN_SCHED: 1129 return (p_cansched(p1, p2, privused)); 1130 1131 case P_CAN_DEBUG: 1132 return (p_candebug(p1, p2, privused)); 1133 1134 default: 1135 panic("p_can: invalid operation"); 1136 } 1137} 1138 1139 1140/* 1141 * Allocate a zeroed cred structure. 1142 */ 1143struct ucred * 1144crget() 1145{ 1146 register struct ucred *cr; 1147 1148 MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK|M_ZERO); 1149 cr->cr_ref = 1; 1150 mtx_init(&cr->cr_mtx, "ucred", MTX_DEF); 1151 return (cr); 1152} 1153 1154/* 1155 * Claim another reference to a ucred structure 1156 */ 1157void 1158crhold(cr) 1159 struct ucred *cr; 1160{ 1161 1162 mtx_lock(&cr->cr_mtx); 1163 cr->cr_ref++; 1164 mtx_unlock(&(cr)->cr_mtx); 1165} 1166 1167 1168/* 1169 * Free a cred structure. 1170 * Throws away space when ref count gets to 0. 1171 */ 1172void 1173crfree(cr) 1174 struct ucred *cr; 1175{ 1176 1177 mtx_lock(&cr->cr_mtx); 1178 if (--cr->cr_ref == 0) { 1179 mtx_destroy(&cr->cr_mtx); 1180 /* 1181 * Some callers of crget(), such as nfs_statfs(), 1182 * allocate a temporary credential, but don't 1183 * allocate a uidinfo structure. 1184 */ 1185 if (cr->cr_uidinfo != NULL) 1186 uifree(cr->cr_uidinfo); 1187 /* 1188 * Free a prison, if any. 1189 */ 1190 if (jailed(cr)) 1191 prison_free(cr->cr_prison); 1192 FREE((caddr_t)cr, M_CRED); 1193 } else { 1194 mtx_unlock(&cr->cr_mtx); 1195 } 1196} 1197 1198/* 1199 * Copy cred structure to a new one and free the old one. 1200 */ 1201struct ucred * 1202crcopy(cr) 1203 struct ucred *cr; 1204{ 1205 struct ucred *newcr; 1206 1207 mtx_lock(&cr->cr_mtx); 1208 if (cr->cr_ref == 1) { 1209 mtx_unlock(&cr->cr_mtx); 1210 return (cr); 1211 } 1212 mtx_unlock(&cr->cr_mtx); 1213 newcr = crdup(cr); 1214 crfree(cr); 1215 return (newcr); 1216} 1217 1218/* 1219 * Dup cred struct to a new held one. 1220 */ 1221struct ucred * 1222crdup(cr) 1223 struct ucred *cr; 1224{ 1225 struct ucred *newcr; 1226 1227 MALLOC(newcr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK); 1228 *newcr = *cr; 1229 mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF); 1230 uihold(newcr->cr_uidinfo); 1231 if (jailed(newcr)) 1232 prison_hold(newcr->cr_prison); 1233 newcr->cr_ref = 1; 1234 return (newcr); 1235} 1236 1237/* 1238 * Get login name, if available. 1239 */ 1240#ifndef _SYS_SYSPROTO_H_ 1241struct getlogin_args { 1242 char *namebuf; 1243 u_int namelen; 1244}; 1245#endif 1246/* ARGSUSED */ 1247int 1248getlogin(p, uap) 1249 struct proc *p; 1250 struct getlogin_args *uap; 1251{ 1252 1253 if (uap->namelen > MAXLOGNAME) 1254 uap->namelen = MAXLOGNAME; 1255 return (copyout((caddr_t) p->p_pgrp->pg_session->s_login, 1256 (caddr_t) uap->namebuf, uap->namelen)); 1257} 1258 1259/* 1260 * Set login name. 1261 */ 1262#ifndef _SYS_SYSPROTO_H_ 1263struct setlogin_args { 1264 char *namebuf; 1265}; 1266#endif 1267/* ARGSUSED */ 1268int 1269setlogin(p, uap) 1270 struct proc *p; 1271 struct setlogin_args *uap; 1272{ 1273 int error; 1274 char logintmp[MAXLOGNAME]; 1275 1276 if ((error = suser_xxx(0, p, PRISON_ROOT))) 1277 return (error); 1278 error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, 1279 sizeof(logintmp), (size_t *)0); 1280 if (error == ENAMETOOLONG) 1281 error = EINVAL; 1282 else if (!error) 1283 (void) memcpy(p->p_pgrp->pg_session->s_login, logintmp, 1284 sizeof(logintmp)); 1285 return (error); 1286} 1287 1288void 1289setsugid(p) 1290 struct proc *p; 1291{ 1292 p->p_flag |= P_SUGID; 1293 if (!(p->p_pfsflags & PF_ISUGID)) 1294 p->p_stops = 0; 1295} 1296 1297/* 1298 * Helper function to change the effective uid of a process 1299 */ 1300void 1301change_euid(p, euid) 1302 struct proc *p; 1303 uid_t euid; 1304{ 1305 struct pcred *pc; 1306 struct uidinfo *uip; 1307 1308 pc = p->p_cred; 1309 /* 1310 * crcopy is essentially a NOP if ucred has a reference count 1311 * of 1, which is true if it has already been copied. 1312 */ 1313 pc->pc_ucred = crcopy(pc->pc_ucred); 1314 uip = pc->pc_ucred->cr_uidinfo; 1315 pc->pc_ucred->cr_uid = euid; 1316 pc->pc_ucred->cr_uidinfo = uifind(euid); 1317 uifree(uip); 1318} 1319 1320/* 1321 * Helper function to change the real uid of a process 1322 * 1323 * The per-uid process count for this process is transfered from 1324 * the old uid to the new uid. 1325 */ 1326void 1327change_ruid(p, ruid) 1328 struct proc *p; 1329 uid_t ruid; 1330{ 1331 struct pcred *pc; 1332 struct uidinfo *uip; 1333 1334 pc = p->p_cred; 1335 (void)chgproccnt(pc->p_uidinfo, -1, 0); 1336 uip = pc->p_uidinfo; 1337 /* It is assumed that pcred is not shared between processes */ 1338 pc->p_ruid = ruid; 1339 pc->p_uidinfo = uifind(ruid); 1340 (void)chgproccnt(pc->p_uidinfo, 1, 0); 1341 uifree(uip); 1342} 1343