Home | History | Annotate | Line # | Download | only in kern
kern_prot.c revision 1.69.2.1
      1 /*	$NetBSD: kern_prot.c,v 1.69.2.1 2002/12/18 01:06:11 gmcgarry Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  * (c) UNIX System Laboratories, Inc.
      7  * All or some portions of this file are derived from material licensed
      8  * to the University of California by American Telephone and Telegraph
      9  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
     10  * the permission of UNIX System Laboratories, Inc.
     11  *
     12  * Redistribution and use in source and binary forms, with or without
     13  * modification, are permitted provided that the following conditions
     14  * are met:
     15  * 1. Redistributions of source code must retain the above copyright
     16  *    notice, this list of conditions and the following disclaimer.
     17  * 2. Redistributions in binary form must reproduce the above copyright
     18  *    notice, this list of conditions and the following disclaimer in the
     19  *    documentation and/or other materials provided with the distribution.
     20  * 3. All advertising materials mentioning features or use of this software
     21  *    must display the following acknowledgement:
     22  *	This product includes software developed by the University of
     23  *	California, Berkeley and its contributors.
     24  * 4. Neither the name of the University nor the names of its contributors
     25  *    may be used to endorse or promote products derived from this software
     26  *    without specific prior written permission.
     27  *
     28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     38  * SUCH DAMAGE.
     39  *
     40  *	@(#)kern_prot.c	8.9 (Berkeley) 2/14/95
     41  */
     42 
     43 /*
     44  * System calls related to processes and protection
     45  */
     46 
     47 #include <sys/cdefs.h>
     48 __KERNEL_RCSID(0, "$NetBSD: kern_prot.c,v 1.69.2.1 2002/12/18 01:06:11 gmcgarry Exp $");
     49 
     50 #include "opt_compat_43.h"
     51 
     52 #include <sys/param.h>
     53 #include <sys/acct.h>
     54 #include <sys/systm.h>
     55 #include <sys/ucred.h>
     56 #include <sys/proc.h>
     57 #include <sys/timeb.h>
     58 #include <sys/pool.h>
     59 #include <sys/times.h>
     60 
     61 #include <sys/mount.h>
     62 #include <sys/syscallargs.h>
     63 
     64 int	sys_getpid(struct proc *, void *, register_t *);
     65 int	sys_getpid_with_ppid(struct proc *, void *, register_t *);
     66 int	sys_getuid(struct proc *, void *, register_t *);
     67 int	sys_getuid_with_euid(struct proc *, void *, register_t *);
     68 int	sys_getgid(struct proc *, void *, register_t *);
     69 int	sys_getgid_with_egid(struct proc *, void *, register_t *);
     70 
     71 struct pool ucred_pool;
     72 
     73 /* ARGSUSED */
     74 int
     75 sys_getpid(p, v, retval)
     76 	struct proc *p;
     77 	void *v;
     78 	register_t *retval;
     79 {
     80 
     81 	*retval = p->p_pid;
     82 	return (0);
     83 }
     84 
     85 /* ARGSUSED */
     86 int
     87 sys_getpid_with_ppid(p, v, retval)
     88 	struct proc *p;
     89 	void *v;
     90 	register_t *retval;
     91 {
     92 
     93 	retval[0] = p->p_pid;
     94 	retval[1] = p->p_pptr->p_pid;
     95 	return (0);
     96 }
     97 
     98 /* ARGSUSED */
     99 int
    100 sys_getppid(p, v, retval)
    101 	struct proc *p;
    102 	void *v;
    103 	register_t *retval;
    104 {
    105 
    106 	*retval = p->p_pptr->p_pid;
    107 	return (0);
    108 }
    109 
    110 /* Get process group ID; note that POSIX getpgrp takes no parameter */
    111 int
    112 sys_getpgrp(p, v, retval)
    113 	struct proc *p;
    114 	void *v;
    115 	register_t *retval;
    116 {
    117 
    118 	*retval = p->p_pgrp->pg_id;
    119 	return (0);
    120 }
    121 
    122 /*
    123  * Return the process group ID of the session leader (session ID)
    124  * for the specified process.
    125  */
    126 int
    127 sys_getsid(p, v, retval)
    128 	struct proc *p;
    129 	void *v;
    130 	register_t *retval;
    131 {
    132 	struct sys_getsid_args /* {
    133 		syscalldarg(pid_t) pid;
    134 	} */ *uap = v;
    135 
    136 	if (SCARG(uap, pid) == 0)
    137 		goto found;
    138 	if ((p = pfind(SCARG(uap, pid))) == 0)
    139 		return (ESRCH);
    140 found:
    141 	*retval = p->p_session->s_sid;
    142 	return (0);
    143 }
    144 
    145 int
    146 sys_getpgid(p, v, retval)
    147 	struct proc *p;
    148 	void *v;
    149 	register_t *retval;
    150 {
    151 	struct sys_getpgid_args /* {
    152 		syscallarg(pid_t) pid;
    153 	} */ *uap = v;
    154 
    155 	if (SCARG(uap, pid) == 0)
    156 		goto found;
    157 	if ((p = pfind(SCARG(uap, pid))) == 0)
    158 		return (ESRCH);
    159 found:
    160 	*retval = p->p_pgid;
    161 	return (0);
    162 }
    163 
    164 /* ARGSUSED */
    165 int
    166 sys_getuid(p, v, retval)
    167 	struct proc *p;
    168 	void *v;
    169 	register_t *retval;
    170 {
    171 
    172 	*retval = p->p_ucred->cr_ruid;
    173 	return (0);
    174 }
    175 
    176 /* ARGSUSED */
    177 int
    178 sys_getuid_with_euid(p, v, retval)
    179 	struct proc *p;
    180 	void *v;
    181 	register_t *retval;
    182 {
    183 
    184 	retval[0] = p->p_ucred->cr_ruid;
    185 	retval[1] = p->p_ucred->cr_uid;
    186 	return (0);
    187 }
    188 
    189 /* ARGSUSED */
    190 int
    191 sys_geteuid(p, v, retval)
    192 	struct proc *p;
    193 	void *v;
    194 	register_t *retval;
    195 {
    196 
    197 	*retval = p->p_ucred->cr_uid;
    198 	return (0);
    199 }
    200 
    201 /* ARGSUSED */
    202 int
    203 sys_getgid(p, v, retval)
    204 	struct proc *p;
    205 	void *v;
    206 	register_t *retval;
    207 {
    208 
    209 	*retval = p->p_ucred->cr_rgid;
    210 	return (0);
    211 }
    212 
    213 /* ARGSUSED */
    214 int
    215 sys_getgid_with_egid(p, v, retval)
    216 	struct proc *p;
    217 	void *v;
    218 	register_t *retval;
    219 {
    220 
    221 	retval[0] = p->p_ucred->cr_rgid;
    222 	retval[1] = p->p_ucred->cr_gid;
    223 	return (0);
    224 }
    225 
    226 /*
    227  * Get effective group ID.  The "egid" is groups[0], and could be obtained
    228  * via getgroups.  This syscall exists because it is somewhat painful to do
    229  * correctly in a library function.
    230  */
    231 /* ARGSUSED */
    232 int
    233 sys_getegid(p, v, retval)
    234 	struct proc *p;
    235 	void *v;
    236 	register_t *retval;
    237 {
    238 
    239 	*retval = p->p_ucred->cr_gid;
    240 	return (0);
    241 }
    242 
    243 int
    244 sys_getgroups(p, v, retval)
    245 	struct proc *p;
    246 	void *v;
    247 	register_t *retval;
    248 {
    249 	struct sys_getgroups_args /* {
    250 		syscallarg(int) gidsetsize;
    251 		syscallarg(gid_t *) gidset;
    252 	} */ *uap = v;
    253 	u_int ngrp;
    254 	int error;
    255 
    256 	if (SCARG(uap, gidsetsize) == 0) {
    257 		*retval = p->p_ucred->cr_ngroups;
    258 		return (0);
    259 	} else if (SCARG(uap, gidsetsize) < 0)
    260 		return (EINVAL);
    261 	ngrp = SCARG(uap, gidsetsize);
    262 	if (ngrp < p->p_ucred->cr_ngroups)
    263 		return (EINVAL);
    264 	ngrp = p->p_ucred->cr_ngroups;
    265 	error = copyout((caddr_t)p->p_ucred->cr_groups,
    266 			(caddr_t)SCARG(uap, gidset), ngrp * sizeof(gid_t));
    267 	if (error)
    268 		return (error);
    269 	*retval = ngrp;
    270 	return (0);
    271 }
    272 
    273 /* ARGSUSED */
    274 int
    275 sys_setsid(p, v, retval)
    276 	struct proc *p;
    277 	void *v;
    278 	register_t *retval;
    279 {
    280 
    281 	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
    282 		return (EPERM);
    283 	} else {
    284 		(void)enterpgrp(p, p->p_pid, 1);
    285 		*retval = p->p_pid;
    286 		return (0);
    287 	}
    288 }
    289 
    290 /*
    291  * set process group (setpgid/old setpgrp)
    292  *
    293  * caller does setpgid(targpid, targpgid)
    294  *
    295  * pgid must be in valid range (EINVAL)
    296  * pid must be caller or child of caller (ESRCH)
    297  * if a child
    298  *	pid must be in same session (EPERM)
    299  *	pid can't have done an exec (EACCES)
    300  * if pgid != pid
    301  * 	there must exist some pid in same session having pgid (EPERM)
    302  * pid must not be session leader (EPERM)
    303  */
    304 /* ARGSUSED */
    305 int
    306 sys_setpgid(curp, v, retval)
    307 	struct proc *curp;
    308 	void *v;
    309 	register_t *retval;
    310 {
    311 	struct sys_setpgid_args /* {
    312 		syscallarg(int) pid;
    313 		syscallarg(int) pgid;
    314 	} */ *uap = v;
    315 	struct proc *targp;			/* target process */
    316 	struct pgrp *pgrp;			/* target pgrp */
    317 
    318 	if (SCARG(uap, pgid) < 0)
    319 		return (EINVAL);
    320 
    321 	if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) {
    322 		if ((targp = pfind(SCARG(uap, pid))) == 0
    323 		    || !inferior(targp, curp))
    324 			return (ESRCH);
    325 		if (targp->p_session != curp->p_session)
    326 			return (EPERM);
    327 		if (targp->p_flag & P_EXEC)
    328 			return (EACCES);
    329 	} else
    330 		targp = curp;
    331 	if (SESS_LEADER(targp))
    332 		return (EPERM);
    333 	if (SCARG(uap, pgid) == 0)
    334 		SCARG(uap, pgid) = targp->p_pid;
    335 	else if (SCARG(uap, pgid) != targp->p_pid)
    336 		if ((pgrp = pgfind(SCARG(uap, pgid))) == 0 ||
    337 	            pgrp->pg_session != curp->p_session)
    338 			return (EPERM);
    339 	return (enterpgrp(targp, SCARG(uap, pgid), 0));
    340 }
    341 
    342 /* ARGSUSED */
    343 int
    344 sys_setuid(p, v, retval)
    345 	struct proc *p;
    346 	void *v;
    347 	register_t *retval;
    348 {
    349 	struct sys_setuid_args /* {
    350 		syscallarg(uid_t) uid;
    351 	} */ *uap = v;
    352 	uid_t uid;
    353 	int error;
    354 
    355 	uid = SCARG(uap, uid);
    356 	if (uid != p->p_ucred->cr_ruid &&
    357 	    (error = suser(p->p_ucred, &p->p_acflag)))
    358 		return (error);
    359 	/*
    360 	 * Check if we are all set, and this is a no-op.
    361 	 */
    362 	if (p->p_ucred->cr_ruid == uid && p->p_ucred->cr_svuid == uid &&
    363 	    p->p_ucred->cr_uid == uid)
    364 		return (0);
    365 	/*
    366 	 * Everything's okay, do it.
    367 	 * Transfer proc count to new user.
    368 	 * Copy credentials so other references do not see our changes.
    369 	 */
    370 	(void)chgproccnt(p->p_ucred->cr_ruid, -1);
    371 	(void)chgproccnt(uid, 1);
    372 	p->p_ucred = crcopy(p->p_ucred);
    373 	p->p_ucred->cr_uid = uid;
    374 	p->p_ucred->cr_ruid = uid;
    375 	p->p_ucred->cr_svuid = uid;
    376 	p_sugid(p);
    377 	return (0);
    378 }
    379 
    380 /* ARGSUSED */
    381 int
    382 sys_seteuid(p, v, retval)
    383 	struct proc *p;
    384 	void *v;
    385 	register_t *retval;
    386 {
    387 	struct sys_seteuid_args /* {
    388 		syscallarg(uid_t) euid;
    389 	} */ *uap = v;
    390 	uid_t euid;
    391 	int error;
    392 
    393 	euid = SCARG(uap, euid);
    394 	if (euid != p->p_ucred->cr_ruid && euid != p->p_ucred->cr_svuid &&
    395 	    (error = suser(p->p_ucred, &p->p_acflag)))
    396 		return (error);
    397 	/*
    398 	 * Check if we are all set, and this is a no-op.
    399 	 */
    400 	if (p->p_ucred->cr_uid == euid)
    401 		return (0);
    402 
    403 	/*
    404 	 * Everything's okay, do it.  Copy credentials so other references do
    405 	 * not see our changes.
    406 	 */
    407 	p->p_ucred = crcopy(p->p_ucred);
    408 	p->p_ucred->cr_uid = euid;
    409 	p_sugid(p);
    410 	return (0);
    411 }
    412 
    413 int
    414 sys_setreuid(p, v, retval)
    415 	struct proc *p;
    416 	void *v;
    417 	register_t *retval;
    418 {
    419 	struct sys_setreuid_args /* {
    420 		syscallarg(uid_t) ruid;
    421 		syscallarg(uid_t) euid;
    422 	} */ *uap = v;
    423 	uid_t ruid, euid;
    424 	int error, changed = 0;
    425 
    426 	ruid = SCARG(uap, ruid);
    427 	euid = SCARG(uap, euid);
    428 
    429 	if (ruid != (uid_t)-1 &&
    430 	    ruid != p->p_ucred->cr_ruid && ruid != p->p_ucred->cr_uid &&
    431 	    (error = suser(p->p_ucred, &p->p_acflag)))
    432 		return (error);
    433 
    434 	if (euid != (uid_t)-1 &&
    435 	    euid != p->p_ucred->cr_ruid && euid != p->p_ucred->cr_uid &&
    436 	    euid != p->p_ucred->cr_svuid &&
    437 	    (error = suser(p->p_ucred, &p->p_acflag)))
    438 		return (error);
    439 
    440 	/*
    441 	 * Copy credentials so other references do not see our changes.
    442 	 */
    443 	p->p_ucred = crcopy(p->p_ucred);
    444 
    445 	if (euid != (uid_t)-1 && euid != p->p_ucred->cr_uid) {
    446 		p->p_ucred->cr_uid = euid;
    447 		changed++;
    448 	}
    449 
    450 	if (ruid != (uid_t)-1 && (p->p_ucred->cr_ruid != ruid ||
    451 	    p->p_ucred->cr_svuid != p->p_ucred->cr_uid)) {
    452 		(void)chgproccnt(p->p_ucred->cr_ruid, -1);
    453 		(void)chgproccnt(ruid, 1);
    454 		p->p_ucred->cr_ruid = ruid;
    455 		p->p_ucred->cr_svuid = p->p_ucred->cr_uid;
    456 		changed++;
    457 	}
    458 
    459 	if (changed)
    460 		p_sugid(p);
    461 	return (0);
    462 }
    463 
    464 /* ARGSUSED */
    465 int
    466 sys_setgid(p, v, retval)
    467 	struct proc *p;
    468 	void *v;
    469 	register_t *retval;
    470 {
    471 	struct sys_setgid_args /* {
    472 		syscallarg(gid_t) gid;
    473 	} */ *uap = v;
    474 	gid_t gid;
    475 	int error;
    476 
    477 	gid = SCARG(uap, gid);
    478 	if (gid != p->p_ucred->cr_rgid &&
    479 	    (error = suser(p->p_ucred, &p->p_acflag)))
    480 		return (error);
    481 	/*
    482 	 * Check if we are all set, and this is a no-op.
    483 	 */
    484 	if (p->p_ucred->cr_gid == gid && p->p_ucred->cr_rgid == gid &&
    485 	    p->p_ucred->cr_svgid == gid)
    486 		return (0);
    487 
    488 	p->p_ucred = crcopy(p->p_ucred);
    489 	p->p_ucred->cr_gid = gid;
    490 	p->p_ucred->cr_rgid = gid;
    491 	p->p_ucred->cr_svgid = gid;
    492 	p_sugid(p);
    493 	return (0);
    494 }
    495 
    496 /* ARGSUSED */
    497 int
    498 sys_setegid(p, v, retval)
    499 	struct proc *p;
    500 	void *v;
    501 	register_t *retval;
    502 {
    503 	struct sys_setegid_args /* {
    504 		syscallarg(gid_t) egid;
    505 	} */ *uap = v;
    506 	gid_t egid;
    507 	int error;
    508 
    509 	egid = SCARG(uap, egid);
    510 	if (egid != p->p_ucred->cr_rgid && egid != p->p_ucred->cr_svgid &&
    511 	    (error = suser(p->p_ucred, &p->p_acflag)))
    512 		return (error);
    513 	/*
    514 	 * Check if we are all set, and this is a no-op.
    515 	 */
    516 	if (p->p_ucred->cr_gid == egid)
    517 		return (0);
    518 
    519 	p->p_ucred = crcopy(p->p_ucred);
    520 	p->p_ucred->cr_gid = egid;
    521 	p_sugid(p);
    522 	return (0);
    523 }
    524 
    525 int
    526 sys_setregid(p, v, retval)
    527 	struct proc *p;
    528 	void *v;
    529 	register_t *retval;
    530 {
    531 	struct sys_setregid_args /* {
    532 		syscallarg(gid_t) rgid;
    533 		syscallarg(gid_t) egid;
    534 	} */ *uap = v;
    535 	gid_t rgid, egid;
    536 	int error, changed = 0;
    537 
    538 	rgid = SCARG(uap, rgid);
    539 	egid = SCARG(uap, egid);
    540 
    541 	if (rgid != (gid_t)-1 &&
    542 	    rgid != p->p_ucred->cr_rgid && rgid != p->p_ucred->cr_gid &&
    543 	    (error = suser(p->p_ucred, &p->p_acflag)))
    544 		return (error);
    545 
    546 	if (egid != (gid_t)-1 &&
    547 	    egid != p->p_ucred->cr_rgid && egid != p->p_ucred->cr_gid &&
    548 	    egid != p->p_ucred->cr_svgid &&
    549 	    (error = suser(p->p_ucred, &p->p_acflag)))
    550 		return (error);
    551 
    552 	/*
    553 	 * Copy credentials so other references do not see our changes.
    554 	 */
    555 	p->p_ucred = crcopy(p->p_ucred);
    556 
    557 	if (egid != (gid_t)-1 && p->p_ucred->cr_gid != egid) {
    558 		p->p_ucred->cr_gid = egid;
    559 		changed++;
    560 	}
    561 
    562 	if (rgid != (gid_t)-1 && (p->p_ucred->cr_rgid != rgid ||
    563 	    p->p_ucred->cr_svgid != p->p_ucred->cr_gid)) {
    564 		p->p_ucred->cr_rgid = rgid;
    565 		p->p_ucred->cr_svgid = p->p_ucred->cr_gid;
    566 		changed++;
    567 	}
    568 
    569 	if (changed)
    570 		p_sugid(p);
    571 	return (0);
    572 }
    573 
    574 int
    575 sys_issetugid(p, v, retval)
    576 	struct proc *p;
    577 	void *v;
    578 	register_t *retval;
    579 {
    580 	/*
    581 	 * Note: OpenBSD sets a P_SUGIDEXEC flag set at execve() time,
    582 	 * we use P_SUGID because we consider changing the owners as
    583 	 * "tainting" as well.
    584 	 * This is significant for procs that start as root and "become"
    585 	 * a user without an exec - programs cannot know *everything*
    586 	 * that libc *might* have put in their data segment.
    587 	 */
    588 	*retval = (p->p_flag & P_SUGID) != 0;
    589 	return (0);
    590 }
    591 
    592 /* ARGSUSED */
    593 int
    594 sys_setgroups(p, v, retval)
    595 	struct proc *p;
    596 	void *v;
    597 	register_t *retval;
    598 {
    599 	struct sys_setgroups_args /* {
    600 		syscallarg(int) gidsetsize;
    601 		syscallarg(const gid_t *) gidset;
    602 	} */ *uap = v;
    603 	int ngrp;
    604 	int error;
    605 	gid_t grp[NGROUPS];
    606 	size_t grsize;
    607 
    608 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    609 		return (error);
    610 
    611 	ngrp = SCARG(uap, gidsetsize);
    612 	if ((u_int)ngrp > NGROUPS)
    613 		return (EINVAL);
    614 
    615 	grsize = ngrp * sizeof(gid_t);
    616 	error = copyin(SCARG(uap, gidset), grp, grsize);
    617 	if (error)
    618 		return (error);
    619 	/*
    620 	 * Check if this is a no-op.
    621 	 */
    622 	if (p->p_ucred->cr_ngroups == (u_int) ngrp &&
    623 	    memcmp(grp, p->p_ucred->cr_groups, grsize) == 0)
    624 		return (0);
    625 
    626 	p->p_ucred = crcopy(p->p_ucred);
    627 	(void)memcpy(p->p_ucred->cr_groups, grp, grsize);
    628 	p->p_ucred->cr_ngroups = ngrp;
    629 	p_sugid(p);
    630 	return (0);
    631 }
    632 
    633 /*
    634  * Get login name, if available.
    635  */
    636 /* ARGSUSED */
    637 int
    638 sys___getlogin(p, v, retval)
    639 	struct proc *p;
    640 	void *v;
    641 	register_t *retval;
    642 {
    643 	struct sys___getlogin_args /* {
    644 		syscallarg(char *) namebuf;
    645 		syscallarg(size_t) namelen;
    646 	} */ *uap = v;
    647 
    648 	if (SCARG(uap, namelen) > sizeof(p->p_pgrp->pg_session->s_login))
    649 		SCARG(uap, namelen) = sizeof(p->p_pgrp->pg_session->s_login);
    650 	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
    651 	    (caddr_t) SCARG(uap, namebuf), SCARG(uap, namelen)));
    652 }
    653 
    654 /*
    655  * Set login name.
    656  */
    657 /* ARGSUSED */
    658 int
    659 sys_setlogin(p, v, retval)
    660 	struct proc *p;
    661 	void *v;
    662 	register_t *retval;
    663 {
    664 	struct sys_setlogin_args /* {
    665 		syscallarg(const char *) namebuf;
    666 	} */ *uap = v;
    667 	int error;
    668 
    669 	if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
    670 		return (error);
    671 	error = copyinstr(SCARG(uap, namebuf), p->p_pgrp->pg_session->s_login,
    672 	    sizeof(p->p_pgrp->pg_session->s_login) - 1, (size_t *)0);
    673 	if (error == ENAMETOOLONG)
    674 		error = EINVAL;
    675 	return (error);
    676 }
    677 
    678 /*
    679  * Check if gid is a member of the group set.
    680  */
    681 int
    682 groupmember(gid, cred)
    683 	gid_t gid;
    684 	struct ucred *cred;
    685 {
    686 	gid_t *gp;
    687 	gid_t *egp;
    688 
    689 	egp = &(cred->cr_groups[cred->cr_ngroups]);
    690 	for (gp = cred->cr_groups; gp < egp; gp++)
    691 		if (*gp == gid)
    692 			return (1);
    693 	return (0);
    694 }
    695 
    696 /*
    697  * Test whether the specified credentials imply "super-user"
    698  * privilege; if so, and we have accounting info, set the flag
    699  * indicating use of super-powers.
    700  * Returns 0 or error.
    701  */
    702 int
    703 suser(cred, acflag)
    704 	struct ucred *cred;
    705 	u_short *acflag;
    706 {
    707 	if (cred->cr_uid == 0) {
    708 		if (acflag)
    709 			*acflag |= ASU;
    710 		return (0);
    711 	}
    712 	return (EPERM);
    713 }
    714 
    715 /*
    716  * Allocate a zeroed cred structure.
    717  */
    718 struct ucred *
    719 crget()
    720 {
    721 	struct ucred *cred;
    722 
    723 	cred = pool_get(&ucred_pool, PR_WAITOK);
    724 	memset((caddr_t)cred, 0, sizeof(struct ucred));
    725 	cred->cr_ref = 1;
    726 	return (cred);
    727 }
    728 
    729 /*
    730  * Free a cred structure.
    731  * Throws away space when ref count gets to 0.
    732  */
    733 void
    734 crfree(cred)
    735 	struct ucred *cred;
    736 {
    737 
    738 	if (--cred->cr_ref == 0)
    739 		pool_put(&ucred_pool, cred);
    740 }
    741 
    742 /*
    743  * Copy cred structure to a new one and free the old one.
    744  */
    745 struct ucred *
    746 crcopy(cred)
    747 	struct ucred *cred;
    748 {
    749 	struct ucred *newcred;
    750 
    751 	if (cred->cr_ref == 1)
    752 		return (cred);
    753 	newcred = crget();
    754 	(void)memcpy(newcred, cred, sizeof(struct ucred));
    755 	crfree(cred);
    756 	newcred->cr_ref = 1;
    757 	return (newcred);
    758 }
    759 
    760 /*
    761  * Dup cred struct to a new held one.
    762  */
    763 struct ucred *
    764 crdup(cred)
    765 	struct ucred *cred;
    766 {
    767 	struct ucred *newcred;
    768 
    769 	newcred = crget();
    770 	(void)memcpy(newcred, cred, sizeof(struct ucred));
    771 	newcred->cr_ref = 1;
    772 	return (newcred);
    773 }
    774 
    775 /*
    776  * convert from userland credentials to kernel one
    777  */
    778 void
    779 crcvt(uc, uuc)
    780 	struct ucred *uc;
    781 	const struct uucred *uuc;
    782 {
    783 	uc->cr_ref = 0;
    784 	uc->cr_uid = uuc->cr_uid;
    785 	uc->cr_gid = uuc->cr_gid;
    786 	uc->cr_ngroups = uuc->cr_ngroups;
    787 	(void)memcpy(uc->cr_groups, uuc->cr_groups, sizeof(uuc->cr_groups));
    788 }
    789 
    790 /*
    791  * Initialise the credentials subsystem.
    792  */
    793 void
    794 crinit(void)
    795 {
    796 
    797         pool_init(&ucred_pool, sizeof(struct ucred), 0, 0, 0, "ucredpl",
    798             &pool_allocator_nointr);
    799 }
    800