xref: /csrg-svn/sys/kern/kern_prot.c (revision 68309)
123372Smckusick /*
263182Sbostic  * Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
365799Sbostic  *	The Regents of the University of California.  All rights reserved.
465771Sbostic  * (c) UNIX System Laboratories, Inc.
565771Sbostic  * All or some portions of this file are derived from material licensed
665771Sbostic  * to the University of California by American Telephone and Telegraph
765771Sbostic  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
865771Sbostic  * the permission of UNIX System Laboratories, Inc.
923372Smckusick  *
1044439Sbostic  * %sccs.include.redist.c%
1137578Smckusick  *
12*68309Scgd  *	@(#)kern_prot.c	8.9 (Berkeley) 02/14/95
1323372Smckusick  */
147420Sroot 
157420Sroot /*
167498Sroot  * System calls related to processes and protection
177420Sroot  */
187420Sroot 
1957048Smckusick #include <sys/param.h>
2057048Smckusick #include <sys/acct.h>
2157048Smckusick #include <sys/systm.h>
2257048Smckusick #include <sys/ucred.h>
2357048Smckusick #include <sys/proc.h>
2457048Smckusick #include <sys/timeb.h>
2557048Smckusick #include <sys/times.h>
2657048Smckusick #include <sys/malloc.h>
277420Sroot 
28*68309Scgd #include <sys/mount.h>
29*68309Scgd #include <sys/syscallargs.h>
3054925Storek 
3143393Skarels /* ARGSUSED */
32*68309Scgd int
getpid(p,uap,retval)3343393Skarels getpid(p, uap, retval)
3443393Skarels 	struct proc *p;
35*68309Scgd 	void *uap;
36*68309Scgd 	register_t *retval;
3743393Skarels {
3837579Smckusick 
3943393Skarels 	*retval = p->p_pid;
4052495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
4147540Skarels 	retval[1] = p->p_pptr->p_pid;
4243393Skarels #endif
4344405Skarels 	return (0);
4443393Skarels }
4543393Skarels 
4643393Skarels /* ARGSUSED */
47*68309Scgd int
getppid(p,uap,retval)4843393Skarels getppid(p, uap, retval)
4943393Skarels 	struct proc *p;
50*68309Scgd 	void *uap;
51*68309Scgd 	register_t *retval;
527498Sroot {
537498Sroot 
5447540Skarels 	*retval = p->p_pptr->p_pid;
5544405Skarels 	return (0);
567498Sroot }
577498Sroot 
5847540Skarels /* Get process group ID; note that POSIX getpgrp takes no parameter */
59*68309Scgd int
getpgrp(p,uap,retval)6043393Skarels getpgrp(p, uap, retval)
6143393Skarels 	struct proc *p;
62*68309Scgd 	void *uap;
63*68309Scgd 	register_t *retval;
647498Sroot {
657498Sroot 
6643393Skarels 	*retval = p->p_pgrp->pg_id;
6744405Skarels 	return (0);
687498Sroot }
697498Sroot 
7043393Skarels /* ARGSUSED */
71*68309Scgd int
getuid(p,uap,retval)7243393Skarels getuid(p, uap, retval)
7343393Skarels 	struct proc *p;
74*68309Scgd 	void *uap;
75*68309Scgd 	register_t *retval;
767420Sroot {
777420Sroot 
7847540Skarels 	*retval = p->p_cred->p_ruid;
7952495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
8047540Skarels 	retval[1] = p->p_ucred->cr_uid;
8143393Skarels #endif
8244405Skarels 	return (0);
837420Sroot }
847420Sroot 
8543393Skarels /* ARGSUSED */
86*68309Scgd int
geteuid(p,uap,retval)8743393Skarels geteuid(p, uap, retval)
8843393Skarels 	struct proc *p;
89*68309Scgd 	void *uap;
90*68309Scgd 	register_t *retval;
917498Sroot {
927498Sroot 
9347540Skarels 	*retval = p->p_ucred->cr_uid;
9444405Skarels 	return (0);
957498Sroot }
967498Sroot 
9743393Skarels /* ARGSUSED */
98*68309Scgd int
getgid(p,uap,retval)9943393Skarels getgid(p, uap, retval)
10043393Skarels 	struct proc *p;
101*68309Scgd 	void *uap;
102*68309Scgd 	register_t *retval;
1037498Sroot {
10443393Skarels 
10547540Skarels 	*retval = p->p_cred->p_rgid;
10652495Storek #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
10747540Skarels 	retval[1] = p->p_ucred->cr_groups[0];
10843393Skarels #endif
10944405Skarels 	return (0);
11043393Skarels }
11143393Skarels 
11243393Skarels /*
11345908Sbostic  * Get effective group ID.  The "egid" is groups[0], and could be obtained
11445908Sbostic  * via getgroups.  This syscall exists because it is somewhat painful to do
11545908Sbostic  * correctly in a library function.
11643393Skarels  */
11743393Skarels /* ARGSUSED */
118*68309Scgd int
getegid(p,uap,retval)11943393Skarels getegid(p, uap, retval)
12043393Skarels 	struct proc *p;
121*68309Scgd 	void *uap;
122*68309Scgd 	register_t *retval;
12343393Skarels {
12447540Skarels 
12547540Skarels 	*retval = p->p_ucred->cr_groups[0];
12644405Skarels 	return (0);
12743393Skarels }
12843393Skarels 
129*68309Scgd int
getgroups(p,uap,retval)13043393Skarels getgroups(p, uap, retval)
13143393Skarels 	struct proc *p;
132*68309Scgd 	register struct getgroups_args /* {
133*68309Scgd 		syscallarg(u_int) gidsetsize;
134*68309Scgd 		syscallarg(gid_t *) gidset;
135*68309Scgd 	} */ *uap;
136*68309Scgd 	register_t *retval;
13743393Skarels {
13847540Skarels 	register struct pcred *pc = p->p_cred;
13944994Skarels 	register u_int ngrp;
14043393Skarels 	int error;
1417498Sroot 
142*68309Scgd 	if ((ngrp = SCARG(uap, gidsetsize)) == 0) {
14347540Skarels 		*retval = pc->pc_ucred->cr_ngroups;
14444405Skarels 		return (0);
14537578Smckusick 	}
14647540Skarels 	if (ngrp < pc->pc_ucred->cr_ngroups)
14744405Skarels 		return (EINVAL);
14847540Skarels 	ngrp = pc->pc_ucred->cr_ngroups;
14955162Smckusick 	if (error = copyout((caddr_t)pc->pc_ucred->cr_groups,
150*68309Scgd 	    (caddr_t)SCARG(uap, gidset), ngrp * sizeof(gid_t)))
15144405Skarels 		return (error);
15244994Skarels 	*retval = ngrp;
15344405Skarels 	return (0);
1547498Sroot }
1557498Sroot 
15643393Skarels /* ARGSUSED */
157*68309Scgd int
setsid(p,uap,retval)15843393Skarels setsid(p, uap, retval)
15947540Skarels 	register struct proc *p;
160*68309Scgd 	void *uap;
161*68309Scgd 	register_t *retval;
16237579Smckusick {
16337579Smckusick 
16443393Skarels 	if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
16544405Skarels 		return (EPERM);
16643393Skarels 	} else {
16757049Smarc 		(void)enterpgrp(p, p->p_pid, 1);
16843393Skarels 		*retval = p->p_pid;
16944405Skarels 		return (0);
17037579Smckusick 	}
17137579Smckusick }
17237579Smckusick 
17337579Smckusick /*
17447540Skarels  * set process group (setpgid/old setpgrp)
17537579Smckusick  *
17647972Smarc  * caller does setpgid(targpid, targpgid)
17740667Skarels  *
17840667Skarels  * pid must be caller or child of caller (ESRCH)
17940667Skarels  * if a child
18040667Skarels  *	pid must be in same session (EPERM)
18140667Skarels  *	pid can't have done an exec (EACCES)
18240667Skarels  * if pgid != pid
18340667Skarels  * 	there must exist some pid in same session having pgid (EPERM)
18440667Skarels  * pid must not be session leader (EPERM)
18537579Smckusick  */
18643393Skarels /* ARGSUSED */
187*68309Scgd int
setpgid(curp,uap,retval)18847972Smarc setpgid(curp, uap, retval)
18947972Smarc 	struct proc *curp;
190*68309Scgd 	register struct setpgid_args /* {
191*68309Scgd 		syscallarg(int) pid;
192*68309Scgd 		syscallarg(int) pgid;
193*68309Scgd 	} */ *uap;
194*68309Scgd 	register_t *retval;
19543393Skarels {
19647972Smarc 	register struct proc *targp;		/* target process */
19748990Skarels 	register struct pgrp *pgrp;		/* target pgrp */
1987498Sroot 
199*68309Scgd 	if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != curp->p_pid) {
200*68309Scgd 		if ((targp = pfind(SCARG(uap, pid))) == 0 || !inferior(targp))
20144405Skarels 			return (ESRCH);
20247972Smarc 		if (targp->p_session != curp->p_session)
20344405Skarels 			return (EPERM);
20464586Sbostic 		if (targp->p_flag & P_EXEC)
20544405Skarels 			return (EACCES);
20643393Skarels 	} else
20747972Smarc 		targp = curp;
20847972Smarc 	if (SESS_LEADER(targp))
20944405Skarels 		return (EPERM);
210*68309Scgd 	if (SCARG(uap, pgid) == 0)
211*68309Scgd 		SCARG(uap, pgid) = targp->p_pid;
212*68309Scgd 	else if (SCARG(uap, pgid) != targp->p_pid)
213*68309Scgd 		if ((pgrp = pgfind(SCARG(uap, pgid))) == 0 ||
21448990Skarels 	            pgrp->pg_session != curp->p_session)
21545908Sbostic 			return (EPERM);
216*68309Scgd 	return (enterpgrp(targp, SCARG(uap, pgid), 0));
2177498Sroot }
2187498Sroot 
21943393Skarels /* ARGSUSED */
220*68309Scgd int
setuid(p,uap,retval)22143393Skarels setuid(p, uap, retval)
22247540Skarels 	struct proc *p;
223*68309Scgd 	struct setuid_args /* {
224*68309Scgd 		syscallarg(uid_t) uid;
225*68309Scgd 	} */ *uap;
226*68309Scgd 	register_t *retval;
2277420Sroot {
22847540Skarels 	register struct pcred *pc = p->p_cred;
22943393Skarels 	register uid_t uid;
23043393Skarels 	int error;
23143393Skarels 
232*68309Scgd 	uid = SCARG(uap, uid);
23347540Skarels 	if (uid != pc->p_ruid &&
23447540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
23544405Skarels 		return (error);
23643393Skarels 	/*
23755403Smckusick 	 * Everything's okay, do it.
23855403Smckusick 	 * Transfer proc count to new user.
23955403Smckusick 	 * Copy credentials so other references do not see our changes.
24043393Skarels 	 */
24155403Smckusick 	(void)chgproccnt(pc->p_ruid, -1);
24255403Smckusick 	(void)chgproccnt(uid, 1);
24347540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
24447540Skarels 	pc->pc_ucred->cr_uid = uid;
24547540Skarels 	pc->p_ruid = uid;
24647540Skarels 	pc->p_svuid = uid;
24764586Sbostic 	p->p_flag |= P_SUGID;
24844405Skarels 	return (0);
24943393Skarels }
25043393Skarels 
25143393Skarels /* ARGSUSED */
252*68309Scgd int
seteuid(p,uap,retval)25343393Skarels seteuid(p, uap, retval)
25447540Skarels 	struct proc *p;
255*68309Scgd 	struct seteuid_args /* {
256*68309Scgd 		syscallarg(uid_t) euid;
257*68309Scgd 	} */ *uap;
258*68309Scgd 	register_t *retval;
25943393Skarels {
26047540Skarels 	register struct pcred *pc = p->p_cred;
26143393Skarels 	register uid_t euid;
26243393Skarels 	int error;
26343393Skarels 
264*68309Scgd 	euid = SCARG(uap, euid);
26547540Skarels 	if (euid != pc->p_ruid && euid != pc->p_svuid &&
26647540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
26744405Skarels 		return (error);
26843393Skarels 	/*
26945908Sbostic 	 * Everything's okay, do it.  Copy credentials so other references do
27045908Sbostic 	 * not see our changes.
27143393Skarels 	 */
27247540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
27347540Skarels 	pc->pc_ucred->cr_uid = euid;
27464586Sbostic 	p->p_flag |= P_SUGID;
27544405Skarels 	return (0);
27643393Skarels }
27743393Skarels 
27843393Skarels /* ARGSUSED */
279*68309Scgd int
setgid(p,uap,retval)28043393Skarels setgid(p, uap, retval)
28143393Skarels 	struct proc *p;
282*68309Scgd 	struct setgid_args /* {
283*68309Scgd 		syscallarg(gid_t) gid;
284*68309Scgd 	} */ *uap;
285*68309Scgd 	register_t *retval;
28643393Skarels {
28747540Skarels 	register struct pcred *pc = p->p_cred;
28843393Skarels 	register gid_t gid;
28943393Skarels 	int error;
29043393Skarels 
291*68309Scgd 	gid = SCARG(uap, gid);
29247540Skarels 	if (gid != pc->p_rgid && (error = suser(pc->pc_ucred, &p->p_acflag)))
29344405Skarels 		return (error);
29447540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
29547540Skarels 	pc->pc_ucred->cr_groups[0] = gid;
29647540Skarels 	pc->p_rgid = gid;
29747540Skarels 	pc->p_svgid = gid;		/* ??? */
29864586Sbostic 	p->p_flag |= P_SUGID;
29944405Skarels 	return (0);
30043393Skarels }
30143393Skarels 
30243393Skarels /* ARGSUSED */
303*68309Scgd int
setegid(p,uap,retval)30443393Skarels setegid(p, uap, retval)
30543393Skarels 	struct proc *p;
306*68309Scgd 	struct setegid_args /* {
307*68309Scgd 		syscallarg(gid_t) egid;
308*68309Scgd 	} */ *uap;
309*68309Scgd 	register_t *retval;
31043393Skarels {
31147540Skarels 	register struct pcred *pc = p->p_cred;
31243393Skarels 	register gid_t egid;
31343393Skarels 	int error;
31443393Skarels 
315*68309Scgd 	egid = SCARG(uap, egid);
31647540Skarels 	if (egid != pc->p_rgid && egid != pc->p_svgid &&
31747540Skarels 	    (error = suser(pc->pc_ucred, &p->p_acflag)))
31844405Skarels 		return (error);
31947540Skarels 	pc->pc_ucred = crcopy(pc->pc_ucred);
32047540Skarels 	pc->pc_ucred->cr_groups[0] = egid;
32164586Sbostic 	p->p_flag |= P_SUGID;
32244405Skarels 	return (0);
32343393Skarels }
32443393Skarels 
32543393Skarels /* ARGSUSED */
326*68309Scgd int
setgroups(p,uap,retval)32743393Skarels setgroups(p, uap, retval)
32843393Skarels 	struct proc *p;
329*68309Scgd 	struct setgroups_args /* {
330*68309Scgd 		syscallarg(u_int) gidsetsize;
331*68309Scgd 		syscallarg(gid_t *) gidset;
332*68309Scgd 	} */ *uap;
333*68309Scgd 	register_t *retval;
33443393Skarels {
33547540Skarels 	register struct pcred *pc = p->p_cred;
33644994Skarels 	register u_int ngrp;
33755162Smckusick 	int error;
3387498Sroot 
33947540Skarels 	if (error = suser(pc->pc_ucred, &p->p_acflag))
34044405Skarels 		return (error);
341*68309Scgd 	ngrp = SCARG(uap, gidsetsize);
342*68309Scgd 	if (ngrp < 1 || ngrp > NGROUPS)
34344405Skarels 		return (EINVAL);
34455162Smckusick 	pc->pc_ucred = crcopy(pc->pc_ucred);
345*68309Scgd 	if (error = copyin((caddr_t)SCARG(uap, gidset),
34655162Smckusick 	    (caddr_t)pc->pc_ucred->cr_groups, ngrp * sizeof(gid_t)))
34744405Skarels 		return (error);
34847540Skarels 	pc->pc_ucred->cr_ngroups = ngrp;
34964586Sbostic 	p->p_flag |= P_SUGID;
35044405Skarels 	return (0);
3517498Sroot }
3527498Sroot 
35355163Smckusick #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
35455163Smckusick /* ARGSUSED */
355*68309Scgd int
compat_43_setreuid(p,uap,retval)356*68309Scgd compat_43_setreuid(p, uap, retval)
35755163Smckusick 	register struct proc *p;
358*68309Scgd 	struct compat_43_setreuid_args /* {
359*68309Scgd 		syscallarg(int) ruid;
360*68309Scgd 		syscallarg(int) euid;
361*68309Scgd 	} */ *uap;
362*68309Scgd 	register_t *retval;
36355163Smckusick {
36455163Smckusick 	register struct pcred *pc = p->p_cred;
36567875Shibler 	union {
36667875Shibler 		struct setuid_args sa;
36767875Shibler 		struct seteuid_args ea;
36867875Shibler 	} args;
36955163Smckusick 
37055163Smckusick 	/*
37167875Shibler 	 * If ruid == euid then setreuid is being used to emulate setuid,
37267875Shibler 	 * just do it.
37355163Smckusick 	 */
374*68309Scgd 	if (SCARG(uap, ruid) != -1 && SCARG(uap, ruid) == SCARG(uap, euid)) {
375*68309Scgd 		SCARG(&args.sa, uid) = SCARG(uap, ruid);
37667875Shibler 		return (setuid(p, &args.sa, retval));
37767875Shibler 	}
37867875Shibler 	/*
37967875Shibler 	 * Otherwise we assume that the intent of setting ruid is to be
38067875Shibler 	 * able to get back ruid priviledge (i.e. swapping ruid and euid).
38167875Shibler 	 * So we make sure that we will be able to do so, but do not
38267875Shibler 	 * actually set the ruid.
38367875Shibler 	 */
384*68309Scgd 	if (SCARG(uap, ruid) != (uid_t)-1 && SCARG(uap, ruid) != pc->p_ruid &&
385*68309Scgd 	    SCARG(uap, ruid) != pc->p_svuid)
38655163Smckusick 		return (EPERM);
387*68309Scgd 	if (SCARG(uap, euid) == (uid_t)-1)
38855163Smckusick 		return (0);
389*68309Scgd 	SCARG(&args.ea, euid) = SCARG(uap, euid);
39067875Shibler 	return (seteuid(p, &args.ea, retval));
39155163Smckusick }
39255163Smckusick 
39355163Smckusick /* ARGSUSED */
394*68309Scgd int
compat_43_setregid(p,uap,retval)395*68309Scgd compat_43_setregid(p, uap, retval)
39655163Smckusick 	register struct proc *p;
397*68309Scgd 	struct compat_43_setregid_args /* {
398*68309Scgd 		syscallarg(int) rgid;
399*68309Scgd 		syscallarg(int) egid;
400*68309Scgd 	} */ *uap;
401*68309Scgd 	register_t *retval;
40255163Smckusick {
40355163Smckusick 	register struct pcred *pc = p->p_cred;
40467875Shibler 	union {
40567875Shibler 		struct setgid_args sa;
40667875Shibler 		struct setegid_args ea;
40767875Shibler 	} args;
40855163Smckusick 
40955163Smckusick 	/*
41067875Shibler 	 * If rgid == egid then setreuid is being used to emulate setgid,
41167875Shibler 	 * just do it.
41255163Smckusick 	 */
413*68309Scgd 	if (SCARG(uap, rgid) != -1 && SCARG(uap, rgid) == SCARG(uap, egid)) {
414*68309Scgd 		SCARG(&args.sa, gid) = SCARG(uap, rgid);
41567875Shibler 		return (setgid(p, &args.sa, retval));
41667875Shibler 	}
41767875Shibler 	/*
41867875Shibler 	 * Otherwise we assume that the intent of setting rgid is to be
41967875Shibler 	 * able to get back rgid priviledge (i.e. swapping rgid and egid).
42067875Shibler 	 * So we make sure that we will be able to do so, but do not
42167875Shibler 	 * actually set the rgid.
42267875Shibler 	 */
423*68309Scgd 	if (SCARG(uap, rgid) != (gid_t)-1 && SCARG(uap, rgid) != pc->p_rgid &&
424*68309Scgd 	    SCARG(uap, rgid) != pc->p_svgid)
42555163Smckusick 		return (EPERM);
426*68309Scgd 	if (SCARG(uap, egid) == (gid_t)-1)
42755163Smckusick 		return (0);
428*68309Scgd 	SCARG(&args.ea, egid) = SCARG(uap, egid);
42967875Shibler 	return (setegid(p, &args.ea, retval));
43055163Smckusick }
43155163Smckusick #endif /* defined(COMPAT_43) || defined(COMPAT_SUNOS) */
43255163Smckusick 
4337498Sroot /*
43437578Smckusick  * Check if gid is a member of the group set.
43511810Ssam  */
436*68309Scgd int
groupmember(gid,cred)43737578Smckusick groupmember(gid, cred)
43826275Skarels 	gid_t gid;
43937578Smckusick 	register struct ucred *cred;
4407866Sroot {
44118362Skarels 	register gid_t *gp;
44237578Smckusick 	gid_t *egp;
4437866Sroot 
44437578Smckusick 	egp = &(cred->cr_groups[cred->cr_ngroups]);
44537578Smckusick 	for (gp = cred->cr_groups; gp < egp; gp++)
4467866Sroot 		if (*gp == gid)
44737578Smckusick 			return (1);
44837578Smckusick 	return (0);
4497866Sroot }
4507866Sroot 
45111810Ssam /*
45246293Skarels  * Test whether the specified credentials imply "super-user"
45346293Skarels  * privilege; if so, and we have accounting info, set the flag
45446293Skarels  * indicating use of super-powers.
45546293Skarels  * Returns 0 or error.
45611810Ssam  */
457*68309Scgd int
suser(cred,acflag)45837578Smckusick suser(cred, acflag)
45937578Smckusick 	struct ucred *cred;
46068171Scgd 	u_short *acflag;
4617866Sroot {
46237578Smckusick 	if (cred->cr_uid == 0) {
46337578Smckusick 		if (acflag)
46437578Smckusick 			*acflag |= ASU;
46537578Smckusick 		return (0);
46618362Skarels 	}
46737578Smckusick 	return (EPERM);
4687866Sroot }
46911810Ssam 
47011810Ssam /*
47137578Smckusick  * Allocate a zeroed cred structure.
47211810Ssam  */
47337578Smckusick struct ucred *
crget()47437578Smckusick crget()
47511810Ssam {
47637578Smckusick 	register struct ucred *cr;
47711810Ssam 
47837578Smckusick 	MALLOC(cr, struct ucred *, sizeof(*cr), M_CRED, M_WAITOK);
47937578Smckusick 	bzero((caddr_t)cr, sizeof(*cr));
48037578Smckusick 	cr->cr_ref = 1;
48143393Skarels 	return (cr);
48211810Ssam }
48337085Skfall 
48437085Skfall /*
48537578Smckusick  * Free a cred structure.
48637578Smckusick  * Throws away space when ref count gets to 0.
48737085Skfall  */
48868171Scgd void
crfree(cr)48937578Smckusick crfree(cr)
49037578Smckusick 	struct ucred *cr;
49137578Smckusick {
49265537Sbostic 	int s;
49337085Skfall 
49465537Sbostic 	s = splimp();				/* ??? */
49565537Sbostic 	if (--cr->cr_ref == 0)
49665537Sbostic 		FREE((caddr_t)cr, M_CRED);
49737578Smckusick 	(void) splx(s);
49837578Smckusick }
49937578Smckusick 
50037578Smckusick /*
50137578Smckusick  * Copy cred structure to a new one and free the old one.
50237578Smckusick  */
50337578Smckusick struct ucred *
crcopy(cr)50437578Smckusick crcopy(cr)
50537578Smckusick 	struct ucred *cr;
50637085Skfall {
50737578Smckusick 	struct ucred *newcr;
50837085Skfall 
50945908Sbostic 	if (cr->cr_ref == 1)
51045908Sbostic 		return (cr);
51137578Smckusick 	newcr = crget();
51237578Smckusick 	*newcr = *cr;
51337578Smckusick 	crfree(cr);
51437578Smckusick 	newcr->cr_ref = 1;
51543393Skarels 	return (newcr);
51637085Skfall }
51737085Skfall 
51837085Skfall /*
51937578Smckusick  * Dup cred struct to a new held one.
52037085Skfall  */
52137578Smckusick struct ucred *
crdup(cr)52237578Smckusick crdup(cr)
52337578Smckusick 	struct ucred *cr;
52437085Skfall {
52537578Smckusick 	struct ucred *newcr;
52637085Skfall 
52737578Smckusick 	newcr = crget();
52837578Smckusick 	*newcr = *cr;
52937578Smckusick 	newcr->cr_ref = 1;
53043393Skarels 	return (newcr);
53137085Skfall }
53237579Smckusick 
53337579Smckusick /*
53440667Skarels  * Get login name, if available.
53537579Smckusick  */
53643393Skarels /* ARGSUSED */
537*68309Scgd int
getlogin(p,uap,retval)53843393Skarels getlogin(p, uap, retval)
53943393Skarels 	struct proc *p;
540*68309Scgd 	struct getlogin_args /* {
541*68309Scgd 		syscallarg(char *) namebuf;
542*68309Scgd 		syscallarg(u_int) namelen;
543*68309Scgd 	} */ *uap;
544*68309Scgd 	register_t *retval;
54543393Skarels {
54637579Smckusick 
547*68309Scgd 	if (SCARG(uap, namelen) > sizeof (p->p_pgrp->pg_session->s_login))
548*68309Scgd 		SCARG(uap, namelen) = sizeof (p->p_pgrp->pg_session->s_login);
54947540Skarels 	return (copyout((caddr_t) p->p_pgrp->pg_session->s_login,
550*68309Scgd 	    (caddr_t) SCARG(uap, namebuf), SCARG(uap, namelen)));
55137579Smckusick }
55237579Smckusick 
55337579Smckusick /*
55440667Skarels  * Set login name.
55537579Smckusick  */
55643393Skarels /* ARGSUSED */
557*68309Scgd int
setlogin(p,uap,retval)55843393Skarels setlogin(p, uap, retval)
55943393Skarels 	struct proc *p;
560*68309Scgd 	struct setlogin_args /* {
561*68309Scgd 		syscallarg(char *) namebuf;
562*68309Scgd 	} */ *uap;
563*68309Scgd 	register_t *retval;
56437579Smckusick {
56540667Skarels 	int error;
56637579Smckusick 
56747540Skarels 	if (error = suser(p->p_ucred, &p->p_acflag))
56844405Skarels 		return (error);
569*68309Scgd 	error = copyinstr((caddr_t) SCARG(uap, namebuf),
57047540Skarels 	    (caddr_t) p->p_pgrp->pg_session->s_login,
57147540Skarels 	    sizeof (p->p_pgrp->pg_session->s_login) - 1, (u_int *)0);
57247540Skarels 	if (error == ENAMETOOLONG)
57340667Skarels 		error = EINVAL;
57444405Skarels 	return (error);
57537579Smckusick }
576