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