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