kern_prot.c revision 1541
11541Srgrimes/*
21541Srgrimes * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes * (c) UNIX System Laboratories, Inc.
51541Srgrimes * All or some portions of this file are derived from material licensed
61541Srgrimes * to the University of California by American Telephone and Telegraph
71541Srgrimes * Co. or Unix System Laboratories, Inc. and are reproduced herein with
81541Srgrimes * the permission of UNIX System Laboratories, Inc.
91541Srgrimes *
101541Srgrimes * Redistribution and use in source and binary forms, with or without
111541Srgrimes * modification, are permitted provided that the following conditions
121541Srgrimes * are met:
131541Srgrimes * 1. Redistributions of source code must retain the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer.
151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer in the
171541Srgrimes *    documentation and/or other materials provided with the distribution.
181541Srgrimes * 3. All advertising materials mentioning features or use of this software
191541Srgrimes *    must display the following acknowledgement:
201541Srgrimes *	This product includes software developed by the University of
211541Srgrimes *	California, Berkeley and its contributors.
221541Srgrimes * 4. Neither the name of the University nor the names of its contributors
231541Srgrimes *    may be used to endorse or promote products derived from this software
241541Srgrimes *    without specific prior written permission.
251541Srgrimes *
261541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
271541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
281541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
291541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
301541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
311541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
321541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
331541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
341541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
351541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
361541Srgrimes * SUCH DAMAGE.
371541Srgrimes *
381541Srgrimes *	@(#)kern_prot.c	8.6 (Berkeley) 1/21/94
391541Srgrimes */
401541Srgrimes
411541Srgrimes/*
421541Srgrimes * System calls related to processes and protection
431541Srgrimes */
441541Srgrimes
451541Srgrimes#include <sys/param.h>
461541Srgrimes#include <sys/acct.h>
471541Srgrimes#include <sys/systm.h>
481541Srgrimes#include <sys/ucred.h>
491541Srgrimes#include <sys/proc.h>
501541Srgrimes#include <sys/timeb.h>
511541Srgrimes#include <sys/times.h>
521541Srgrimes#include <sys/malloc.h>
531541Srgrimes
541541Srgrimesstruct args {
551541Srgrimes	int	dummy;
561541Srgrimes};
571541Srgrimes
581541Srgrimes/* ARGSUSED */
591541Srgrimesgetpid(p, uap, retval)
601541Srgrimes	struct proc *p;
611541Srgrimes	struct args *uap;
621541Srgrimes	int *retval;
631541Srgrimes{
641541Srgrimes
651541Srgrimes	*retval = p->p_pid;
661541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
671541Srgrimes	retval[1] = p->p_pptr->p_pid;
681541Srgrimes#endif
691541Srgrimes	return (0);
701541Srgrimes}
711541Srgrimes
721541Srgrimes/* ARGSUSED */
731541Srgrimesgetppid(p, uap, retval)
741541Srgrimes	struct proc *p;
751541Srgrimes	struct args *uap;
761541Srgrimes	int *retval;
771541Srgrimes{
781541Srgrimes
791541Srgrimes	*retval = p->p_pptr->p_pid;
801541Srgrimes	return (0);
811541Srgrimes}
821541Srgrimes
831541Srgrimes/* Get process group ID; note that POSIX getpgrp takes no parameter */
841541Srgrimesgetpgrp(p, uap, retval)
851541Srgrimes	struct proc *p;
861541Srgrimes	struct args *uap;
871541Srgrimes	int *retval;
881541Srgrimes{
891541Srgrimes
901541Srgrimes	*retval = p->p_pgrp->pg_id;
911541Srgrimes	return (0);
921541Srgrimes}
931541Srgrimes
941541Srgrimes/* ARGSUSED */
951541Srgrimesgetuid(p, uap, retval)
961541Srgrimes	struct proc *p;
971541Srgrimes	struct args *uap;
981541Srgrimes	int *retval;
991541Srgrimes{
1001541Srgrimes
1011541Srgrimes	*retval = p->p_cred->p_ruid;
1021541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1031541Srgrimes	retval[1] = p->p_ucred->cr_uid;
1041541Srgrimes#endif
1051541Srgrimes	return (0);
1061541Srgrimes}
1071541Srgrimes
1081541Srgrimes/* ARGSUSED */
1091541Srgrimesgeteuid(p, uap, retval)
1101541Srgrimes	struct proc *p;
1111541Srgrimes	struct args *uap;
1121541Srgrimes	int *retval;
1131541Srgrimes{
1141541Srgrimes
1151541Srgrimes	*retval = p->p_ucred->cr_uid;
1161541Srgrimes	return (0);
1171541Srgrimes}
1181541Srgrimes
1191541Srgrimes/* ARGSUSED */
1201541Srgrimesgetgid(p, uap, retval)
1211541Srgrimes	struct proc *p;
1221541Srgrimes	struct args *uap;
1231541Srgrimes	int *retval;
1241541Srgrimes{
1251541Srgrimes
1261541Srgrimes	*retval = p->p_cred->p_rgid;
1271541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
1281541Srgrimes	retval[1] = p->p_ucred->cr_groups[0];
1291541Srgrimes#endif
1301541Srgrimes	return (0);
1311541Srgrimes}
1321541Srgrimes
1331541Srgrimes/*
1341541Srgrimes * Get effective group ID.  The "egid" is groups[0], and could be obtained
1351541Srgrimes * via getgroups.  This syscall exists because it is somewhat painful to do
1361541Srgrimes * correctly in a library function.
1371541Srgrimes */
1381541Srgrimes/* ARGSUSED */
1391541Srgrimesgetegid(p, uap, retval)
1401541Srgrimes	struct proc *p;
1411541Srgrimes	struct args *uap;
1421541Srgrimes	int *retval;
1431541Srgrimes{
1441541Srgrimes
1451541Srgrimes	*retval = p->p_ucred->cr_groups[0];
1461541Srgrimes	return (0);
1471541Srgrimes}
1481541Srgrimes
1491541Srgrimesstruct getgroups_args {
1501541Srgrimes	u_int	gidsetsize;
1511541Srgrimes	gid_t	*gidset;
1521541Srgrimes};
1531541Srgrimesgetgroups(p, uap, retval)
1541541Srgrimes	struct proc *p;
1551541Srgrimes	register struct	getgroups_args *uap;
1561541Srgrimes	int *retval;
1571541Srgrimes{
1581541Srgrimes	register struct pcred *pc = p->p_cred;
1591541Srgrimes	register u_int ngrp;
1601541Srgrimes	int error;
1611541Srgrimes
1621541Srgrimes	if ((ngrp = uap->gidsetsize) == 0) {
1631541Srgrimes		*retval = pc->pc_ucred->cr_ngroups;
1641541Srgrimes		return (0);
1651541Srgrimes	}
1661541Srgrimes	if (ngrp < pc->pc_ucred->cr_ngroups)
1671541Srgrimes		return (EINVAL);
1681541Srgrimes	ngrp = pc->pc_ucred->cr_ngroups;
1691541Srgrimes	if (error = copyout((caddr_t)pc->pc_ucred->cr_groups,
1701541Srgrimes	    (caddr_t)uap->gidset, ngrp * sizeof(gid_t)))
1711541Srgrimes		return (error);
1721541Srgrimes	*retval = ngrp;
1731541Srgrimes	return (0);
1741541Srgrimes}
1751541Srgrimes
1761541Srgrimes/* ARGSUSED */
1771541Srgrimessetsid(p, uap, retval)
1781541Srgrimes	register struct proc *p;
1791541Srgrimes	struct args *uap;
1801541Srgrimes	int *retval;
1811541Srgrimes{
1821541Srgrimes
1831541Srgrimes	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
1841541Srgrimes		return (EPERM);
1851541Srgrimes	} else {
1861541Srgrimes		(void)enterpgrp(p, p->p_pid, 1);
1871541Srgrimes		*retval = p->p_pid;
1881541Srgrimes		return (0);
1891541Srgrimes	}
1901541Srgrimes}
1911541Srgrimes
1921541Srgrimes/*
1931541Srgrimes * set process group (setpgid/old setpgrp)
1941541Srgrimes *
1951541Srgrimes * caller does setpgid(targpid, targpgid)
1961541Srgrimes *
1971541Srgrimes * pid must be caller or child of caller (ESRCH)
1981541Srgrimes * if a child
1991541Srgrimes *	pid must be in same session (EPERM)
2001541Srgrimes *	pid can't have done an exec (EACCES)
2011541Srgrimes * if pgid != pid
2021541Srgrimes * 	there must exist some pid in same session having pgid (EPERM)
2031541Srgrimes * pid must not be session leader (EPERM)
2041541Srgrimes */
2051541Srgrimesstruct setpgid_args {
2061541Srgrimes	int	pid;	/* target process id */
2071541Srgrimes	int	pgid;	/* target pgrp id */
2081541Srgrimes};
2091541Srgrimes/* ARGSUSED */
2101541Srgrimessetpgid(curp, uap, retval)
2111541Srgrimes	struct proc *curp;
2121541Srgrimes	register struct setpgid_args *uap;
2131541Srgrimes	int *retval;
2141541Srgrimes{
2151541Srgrimes	register struct proc *targp;		/* target process */
2161541Srgrimes	register struct pgrp *pgrp;		/* target pgrp */
2171541Srgrimes
2181541Srgrimes	if (uap->pid != 0 && uap->pid != curp->p_pid) {
2191541Srgrimes		if ((targp = pfind(uap->pid)) == 0 || !inferior(targp))
2201541Srgrimes			return (ESRCH);
2211541Srgrimes		if (targp->p_session != curp->p_session)
2221541Srgrimes			return (EPERM);
2231541Srgrimes		if (targp->p_flag & P_EXEC)
2241541Srgrimes			return (EACCES);
2251541Srgrimes	} else
2261541Srgrimes		targp = curp;
2271541Srgrimes	if (SESS_LEADER(targp))
2281541Srgrimes		return (EPERM);
2291541Srgrimes	if (uap->pgid == 0)
2301541Srgrimes		uap->pgid = targp->p_pid;
2311541Srgrimes	else if (uap->pgid != targp->p_pid)
2321541Srgrimes		if ((pgrp = pgfind(uap->pgid)) == 0 ||
2331541Srgrimes	            pgrp->pg_session != curp->p_session)
2341541Srgrimes			return (EPERM);
2351541Srgrimes	return (enterpgrp(targp, uap->pgid, 0));
2361541Srgrimes}
2371541Srgrimes
2381541Srgrimesstruct setuid_args {
2391541Srgrimes	uid_t	uid;
2401541Srgrimes};
2411541Srgrimes/* ARGSUSED */
2421541Srgrimessetuid(p, uap, retval)
2431541Srgrimes	struct proc *p;
2441541Srgrimes	struct setuid_args *uap;
2451541Srgrimes	int *retval;
2461541Srgrimes{
2471541Srgrimes	register struct pcred *pc = p->p_cred;
2481541Srgrimes	register uid_t uid;
2491541Srgrimes	int error;
2501541Srgrimes
2511541Srgrimes	uid = uap->uid;
2521541Srgrimes	if (uid != pc->p_ruid &&
2531541Srgrimes	    (error = suser(pc->pc_ucred, &p->p_acflag)))
2541541Srgrimes		return (error);
2551541Srgrimes	/*
2561541Srgrimes	 * Everything's okay, do it.
2571541Srgrimes	 * Transfer proc count to new user.
2581541Srgrimes	 * Copy credentials so other references do not see our changes.
2591541Srgrimes	 */
2601541Srgrimes	(void)chgproccnt(pc->p_ruid, -1);
2611541Srgrimes	(void)chgproccnt(uid, 1);
2621541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
2631541Srgrimes	pc->pc_ucred->cr_uid = uid;
2641541Srgrimes	pc->p_ruid = uid;
2651541Srgrimes	pc->p_svuid = uid;
2661541Srgrimes	p->p_flag |= P_SUGID;
2671541Srgrimes	return (0);
2681541Srgrimes}
2691541Srgrimes
2701541Srgrimesstruct seteuid_args {
2711541Srgrimes	uid_t	euid;
2721541Srgrimes};
2731541Srgrimes/* ARGSUSED */
2741541Srgrimesseteuid(p, uap, retval)
2751541Srgrimes	struct proc *p;
2761541Srgrimes	struct seteuid_args *uap;
2771541Srgrimes	int *retval;
2781541Srgrimes{
2791541Srgrimes	register struct pcred *pc = p->p_cred;
2801541Srgrimes	register uid_t euid;
2811541Srgrimes	int error;
2821541Srgrimes
2831541Srgrimes	euid = uap->euid;
2841541Srgrimes	if (euid != pc->p_ruid && euid != pc->p_svuid &&
2851541Srgrimes	    (error = suser(pc->pc_ucred, &p->p_acflag)))
2861541Srgrimes		return (error);
2871541Srgrimes	/*
2881541Srgrimes	 * Everything's okay, do it.  Copy credentials so other references do
2891541Srgrimes	 * not see our changes.
2901541Srgrimes	 */
2911541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
2921541Srgrimes	pc->pc_ucred->cr_uid = euid;
2931541Srgrimes	p->p_flag |= P_SUGID;
2941541Srgrimes	return (0);
2951541Srgrimes}
2961541Srgrimes
2971541Srgrimesstruct setgid_args {
2981541Srgrimes	gid_t	gid;
2991541Srgrimes};
3001541Srgrimes/* ARGSUSED */
3011541Srgrimessetgid(p, uap, retval)
3021541Srgrimes	struct proc *p;
3031541Srgrimes	struct setgid_args *uap;
3041541Srgrimes	int *retval;
3051541Srgrimes{
3061541Srgrimes	register struct pcred *pc = p->p_cred;
3071541Srgrimes	register gid_t gid;
3081541Srgrimes	int error;
3091541Srgrimes
3101541Srgrimes	gid = uap->gid;
3111541Srgrimes	if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
3121541Srgrimes		return (error);
3131541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3141541Srgrimes	pc->pc_ucred->cr_groups[0] = gid;
3151541Srgrimes	pc->p_rgid = gid;
3161541Srgrimes	pc->p_svgid = gid;		/* ??? */
3171541Srgrimes	p->p_flag |= P_SUGID;
3181541Srgrimes	return (0);
3191541Srgrimes}
3201541Srgrimes
3211541Srgrimesstruct setegid_args {
3221541Srgrimes	gid_t	egid;
3231541Srgrimes};
3241541Srgrimes/* ARGSUSED */
3251541Srgrimessetegid(p, uap, retval)
3261541Srgrimes	struct proc *p;
3271541Srgrimes	struct setegid_args *uap;
3281541Srgrimes	int *retval;
3291541Srgrimes{
3301541Srgrimes	register struct pcred *pc = p->p_cred;
3311541Srgrimes	register gid_t egid;
3321541Srgrimes	int error;
3331541Srgrimes
3341541Srgrimes	egid = uap->egid;
3351541Srgrimes	if (egid != pc->p_rgid && egid != pc->p_svgid &&
3361541Srgrimes	    (error = suser(pc->pc_ucred, &p->p_acflag)))
3371541Srgrimes		return (error);
3381541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3391541Srgrimes	pc->pc_ucred->cr_groups[0] = egid;
3401541Srgrimes	p->p_flag |= P_SUGID;
3411541Srgrimes	return (0);
3421541Srgrimes}
3431541Srgrimes
3441541Srgrimesstruct setgroups_args {
3451541Srgrimes	u_int	gidsetsize;
3461541Srgrimes	gid_t	*gidset;
3471541Srgrimes};
3481541Srgrimes/* ARGSUSED */
3491541Srgrimessetgroups(p, uap, retval)
3501541Srgrimes	struct proc *p;
3511541Srgrimes	struct setgroups_args *uap;
3521541Srgrimes	int *retval;
3531541Srgrimes{
3541541Srgrimes	register struct pcred *pc = p->p_cred;
3551541Srgrimes	register u_int ngrp;
3561541Srgrimes	int error;
3571541Srgrimes
3581541Srgrimes	if (error = suser(pc->pc_ucred, &p->p_acflag))
3591541Srgrimes		return (error);
3601541Srgrimes	if ((ngrp = uap->gidsetsize) > NGROUPS)
3611541Srgrimes		return (EINVAL);
3621541Srgrimes	pc->pc_ucred = crcopy(pc->pc_ucred);
3631541Srgrimes	if (error = copyin((caddr_t)uap->gidset,
3641541Srgrimes	    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))
3651541Srgrimes		return (error);
3661541Srgrimes	pc->pc_ucred->cr_ngroups = ngrp;
3671541Srgrimes	p->p_flag |= P_SUGID;
3681541Srgrimes	return (0);
3691541Srgrimes}
3701541Srgrimes
3711541Srgrimes#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
3721541Srgrimesstruct setreuid_args {
3731541Srgrimes	int	ruid;
3741541Srgrimes	int	euid;
3751541Srgrimes};
3761541Srgrimes/* ARGSUSED */
3771541Srgrimesosetreuid(p, uap, retval)
3781541Srgrimes	register struct proc *p;
3791541Srgrimes	struct setreuid_args *uap;
3801541Srgrimes	int *retval;
3811541Srgrimes{
3821541Srgrimes	register struct pcred *pc = p->p_cred;
3831541Srgrimes	struct seteuid_args args;
3841541Srgrimes
3851541Srgrimes	/*
3861541Srgrimes	 * we assume that the intent of setting ruid is to be able to get
3871541Srgrimes	 * back ruid priviledge. So we make sure that we will be able to
3881541Srgrimes	 * do so, but do not actually set the ruid.
3891541Srgrimes	 */
3901541Srgrimes	if (uap->ruid != (uid_t)-1 && uap->ruid != pc->p_ruid &&
3911541Srgrimes	    uap->ruid != pc->p_svuid)
3921541Srgrimes		return (EPERM);
3931541Srgrimes	if (uap->euid == (uid_t)-1)
3941541Srgrimes		return (0);
3951541Srgrimes	args.euid = uap->euid;
3961541Srgrimes	return (seteuid(p, &args, retval));
3971541Srgrimes}
3981541Srgrimes
3991541Srgrimesstruct setregid_args {
4001541Srgrimes	int	rgid;
4011541Srgrimes	int	egid;
4021541Srgrimes};
4031541Srgrimes/* ARGSUSED */
4041541Srgrimesosetregid(p, uap, retval)
4051541Srgrimes	register struct proc *p;
4061541Srgrimes	struct setregid_args *uap;
4071541Srgrimes	int *retval;
4081541Srgrimes{
4091541Srgrimes	register struct pcred *pc = p->p_cred;
4101541Srgrimes	struct setegid_args args;
4111541Srgrimes
4121541Srgrimes	/*
4131541Srgrimes	 * we assume that the intent of setting rgid is to be able to get
4141541Srgrimes	 * back rgid priviledge. So we make sure that we will be able to
4151541Srgrimes	 * do so, but do not actually set the rgid.
4161541Srgrimes	 */
4171541Srgrimes	if (uap->rgid != (gid_t)-1 && uap->rgid != pc->p_rgid &&
4181541Srgrimes	    uap->rgid != pc->p_svgid)
4191541Srgrimes		return (EPERM);
4201541Srgrimes	if (uap->egid == (gid_t)-1)
4211541Srgrimes		return (0);
4221541Srgrimes	args.egid = uap->egid;
4231541Srgrimes	return (setegid(p, &args, retval));
4241541Srgrimes}
4251541Srgrimes#endif /* defined(COMPAT_43) || defined(COMPAT_SUNOS) */
4261541Srgrimes
4271541Srgrimes/*
4281541Srgrimes * Check if gid is a member of the group set.
4291541Srgrimes */
4301541Srgrimesgroupmember(gid, cred)
4311541Srgrimes	gid_t gid;
4321541Srgrimes	register struct ucred *cred;
4331541Srgrimes{
4341541Srgrimes	register gid_t *gp;
4351541Srgrimes	gid_t *egp;
4361541Srgrimes
4371541Srgrimes	egp = &(cred->cr_groups[cred->cr_ngroups]);
4381541Srgrimes	for (gp = cred->cr_groups; gp < egp; gp++)
4391541Srgrimes		if (*gp == gid)
4401541Srgrimes			return (1);
4411541Srgrimes	return (0);
4421541Srgrimes}
4431541Srgrimes
4441541Srgrimes/*
4451541Srgrimes * Test whether the specified credentials imply "super-user"
4461541Srgrimes * privilege; if so, and we have accounting info, set the flag
4471541Srgrimes * indicating use of super-powers.
4481541Srgrimes * Returns 0 or error.
4491541Srgrimes */
4501541Srgrimessuser(cred, acflag)
4511541Srgrimes	struct ucred *cred;
4521541Srgrimes	short *acflag;
4531541Srgrimes{
4541541Srgrimes	if (cred->cr_uid == 0) {
4551541Srgrimes		if (acflag)
4561541Srgrimes			*acflag |= ASU;
4571541Srgrimes		return (0);
4581541Srgrimes	}
4591541Srgrimes	return (EPERM);
4601541Srgrimes}
4611541Srgrimes
4621541Srgrimes/*
4631541Srgrimes * Allocate a zeroed cred structure.
4641541Srgrimes */
4651541Srgrimesstruct ucred *
4661541Srgrimescrget()
4671541Srgrimes{
4681541Srgrimes	register struct ucred *cr;
4691541Srgrimes
4701541Srgrimes	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
4711541Srgrimes	bzero((caddr_t)cr, sizeof(*cr));
4721541Srgrimes	cr->cr_ref = 1;
4731541Srgrimes	return (cr);
4741541Srgrimes}
4751541Srgrimes
4761541Srgrimes/*
4771541Srgrimes * Free a cred structure.
4781541Srgrimes * Throws away space when ref count gets to 0.
4791541Srgrimes */
4801541Srgrimescrfree(cr)
4811541Srgrimes	struct ucred *cr;
4821541Srgrimes{
4831541Srgrimes	int s;
4841541Srgrimes
4851541Srgrimes	s = splimp();				/* ??? */
4861541Srgrimes	if (--cr->cr_ref == 0)
4871541Srgrimes		FREE((caddr_t)cr, M_CRED);
4881541Srgrimes	(void) splx(s);
4891541Srgrimes}
4901541Srgrimes
4911541Srgrimes/*
4921541Srgrimes * Copy cred structure to a new one and free the old one.
4931541Srgrimes */
4941541Srgrimesstruct ucred *
4951541Srgrimescrcopy(cr)
4961541Srgrimes	struct ucred *cr;
4971541Srgrimes{
4981541Srgrimes	struct ucred *newcr;
4991541Srgrimes
5001541Srgrimes	if (cr->cr_ref == 1)
5011541Srgrimes		return (cr);
5021541Srgrimes	newcr = crget();
5031541Srgrimes	*newcr = *cr;
5041541Srgrimes	crfree(cr);
5051541Srgrimes	newcr->cr_ref = 1;
5061541Srgrimes	return (newcr);
5071541Srgrimes}
5081541Srgrimes
5091541Srgrimes/*
5101541Srgrimes * Dup cred struct to a new held one.
5111541Srgrimes */
5121541Srgrimesstruct ucred *
5131541Srgrimescrdup(cr)
5141541Srgrimes	struct ucred *cr;
5151541Srgrimes{
5161541Srgrimes	struct ucred *newcr;
5171541Srgrimes
5181541Srgrimes	newcr = crget();
5191541Srgrimes	*newcr = *cr;
5201541Srgrimes	newcr->cr_ref = 1;
5211541Srgrimes	return (newcr);
5221541Srgrimes}
5231541Srgrimes
5241541Srgrimes/*
5251541Srgrimes * Get login name, if available.
5261541Srgrimes */
5271541Srgrimesstruct getlogin_args {
5281541Srgrimes	char	*namebuf;
5291541Srgrimes	u_int	namelen;
5301541Srgrimes};
5311541Srgrimes/* ARGSUSED */
5321541Srgrimesgetlogin(p, uap, retval)
5331541Srgrimes	struct proc *p;
5341541Srgrimes	struct getlogin_args *uap;
5351541Srgrimes	int *retval;
5361541Srgrimes{
5371541Srgrimes
5381541Srgrimes	if (uap->namelen > sizeof (p->p_pgrp->pg_session->s_login))
5391541Srgrimes		uap->namelen = sizeof (p->p_pgrp->pg_session->s_login);
5401541Srgrimes	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
5411541Srgrimes	    (caddr_t) uap->namebuf, uap->namelen));
5421541Srgrimes}
5431541Srgrimes
5441541Srgrimes/*
5451541Srgrimes * Set login name.
5461541Srgrimes */
5471541Srgrimesstruct setlogin_args {
5481541Srgrimes	char	*namebuf;
5491541Srgrimes};
5501541Srgrimes/* ARGSUSED */
5511541Srgrimessetlogin(p, uap, retval)
5521541Srgrimes	struct proc *p;
5531541Srgrimes	struct setlogin_args *uap;
5541541Srgrimes	int *retval;
5551541Srgrimes{
5561541Srgrimes	int error;
5571541Srgrimes
5581541Srgrimes	if (error = suser(p->p_ucred, &p->p_acflag))
5591541Srgrimes		return (error);
5601541Srgrimes	error = copyinstr((caddr_t) uap->namebuf,
5611541Srgrimes	    (caddr_t) p->p_pgrp->pg_session->s_login,
5621541Srgrimes	    sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
5631541Srgrimes	if (error == ENAMETOOLONG)
5641541Srgrimes		error = EINVAL;
5651541Srgrimes	return (error);
5661541Srgrimes}
567