o General style, formatting, etc, improvements:

- uid's -> uids
	- whitespace improvements, linewrap improvements
	- reorder copyright more appropriately
	- remove redundant MP SAFE comments, add one "NOT MPSAFE?"
	  for setgroups(), which seems to be the sole un-changed system
	  call in the file.
	- clean up securelevel_g?() functions, improve comments.

Largely submitted by:	bde
This commit is contained in:
Robert Watson
2001-12-02 15:07:10 +00:00
parent 9b3e907904
commit eb725b4e6a
+107 -167
View File
@@ -1,13 +1,12 @@
/*
* Copyright (c) 1982, 1986, 1989, 1990, 1991, 1993
* The Regents of the University of California. All rights reserved.
* Copyright (c) 2000-2001 Robert N. M. Watson. All rights reserved.
* (c) UNIX System Laboratories, Inc.
*
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
* Copyright (c) 2000-2001 Robert N. M. Watson. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -57,17 +56,16 @@
#include <sys/proc.h>
#include <sys/sx.h>
#include <sys/sysproto.h>
#include <sys/jail.h>
#include <sys/malloc.h>
#include <sys/pioctl.h>
#include <sys/resourcevar.h>
#include <sys/sysctl.h>
#include <sys/jail.h>
static MALLOC_DEFINE(M_CRED, "cred", "credentials");
SYSCTL_NODE(_kern, OID_AUTO, security, CTLFLAG_RW, 0,
"Kernel security policy");
SYSCTL_NODE(_kern_security, OID_AUTO, bsd, CTLFLAG_RW, 0,
"BSD security policy");
@@ -76,11 +74,6 @@ struct getpid_args {
int dummy;
};
#endif
/*
* getpid
*/
/*
* MPSAFE
*/
@@ -104,10 +97,6 @@ getpid(td, uap)
return (0);
}
/*
* getppid
*/
#ifndef _SYS_SYSPROTO_H_
struct getppid_args {
int dummy;
@@ -134,9 +123,7 @@ getppid(td, uap)
}
/*
* Get process group ID; note that POSIX getpgrp takes no parameter
*
* MP SAFE
* Get process group ID; note that POSIX getpgrp takes no parameter.
*/
#ifndef _SYS_SYSPROTO_H_
struct getpgrp_args {
@@ -165,7 +152,6 @@ struct getpgid_args {
pid_t pid;
};
#endif
/*
* MPSAFE
*/
@@ -176,10 +162,10 @@ getpgid(td, uap)
{
struct proc *p = td->td_proc;
struct proc *pt;
int error = 0;
int s;
int error, s;
s = mtx_lock_giant(kern_giant_proc);
error = 0;
if (uap->pid == 0)
td->td_retval[0] = p->p_pgrp->pg_id;
else if ((pt = pfind(uap->pid)) == NULL)
@@ -202,7 +188,6 @@ struct getsid_args {
pid_t pid;
};
#endif
/*
* MPSAFE
*/
@@ -213,9 +198,10 @@ getsid(td, uap)
{
struct proc *p = td->td_proc;
struct proc *pt;
int error = 0;
int error;
mtx_lock(&Giant);
error = 0;
if (uap->pid == 0)
td->td_retval[0] = p->p_session->s_sid;
else if ((pt = pfind(uap->pid)) == NULL)
@@ -230,16 +216,11 @@ getsid(td, uap)
return (error);
}
/*
* getuid() - MP SAFE
*/
#ifndef _SYS_SYSPROTO_H_
struct getuid_args {
int dummy;
};
#endif
/*
* MPSAFE
*/
@@ -260,15 +241,14 @@ getuid(td, uap)
return (0);
}
/*
* geteuid() - MP SAFE
*/
#ifndef _SYS_SYSPROTO_H_
struct geteuid_args {
int dummy;
};
#endif
/*
* MPSAFE
*/
/* ARGSUSED */
int
geteuid(td, uap)
@@ -281,15 +261,11 @@ geteuid(td, uap)
return (0);
}
/*
* getgid() - MP SAFE
*/
#ifndef _SYS_SYSPROTO_H_
struct getgid_args {
int dummy;
};
#endif
/*
* MPSAFE
*/
@@ -320,7 +296,6 @@ struct getegid_args {
int dummy;
};
#endif
/*
* MPSAFE
*/
@@ -350,18 +325,18 @@ struct getgroups_args {
int
getgroups(td, uap)
struct thread *td;
register struct getgroups_args *uap;
register struct getgroups_args *uap;
{
struct ucred *cred;
struct proc *p = td->td_proc;
u_int ngrp;
int error = 0;
int error;
mtx_lock(&Giant);
error = 0;
cred = p->p_ucred;
if ((ngrp = uap->gidsetsize) == 0) {
td->td_retval[0] = cred->cr_ngroups;
error = 0;
goto done2;
}
if (ngrp < cred->cr_ngroups) {
@@ -370,9 +345,8 @@ getgroups(td, uap)
}
ngrp = cred->cr_ngroups;
if ((error = copyout((caddr_t)cred->cr_groups,
(caddr_t)uap->gidset, ngrp * sizeof(gid_t)))) {
(caddr_t)uap->gidset, ngrp * sizeof(gid_t))))
goto done2;
}
td->td_retval[0] = ngrp;
done2:
mtx_unlock(&Giant);
@@ -384,7 +358,6 @@ struct setsid_args {
int dummy;
};
#endif
/*
* MPSAFE
*/
@@ -398,9 +371,9 @@ setsid(td, uap)
struct proc *p = td->td_proc;
mtx_lock(&Giant);
if (p->p_pgid == p->p_pid || pgfind(p->p_pid)) {
if (p->p_pgid == p->p_pid || pgfind(p->p_pid))
error = EPERM;
} else {
else {
(void)enterpgrp(p, p->p_pid, 1);
td->td_retval[0] = p->p_pid;
error = 0;
@@ -424,8 +397,8 @@ setsid(td, uap)
*/
#ifndef _SYS_SYSPROTO_H_
struct setpgid_args {
int pid; /* target process id */
int pgid; /* target pgrp id */
int pid; /* target process id */
int pgid; /* target pgrp id */
};
#endif
/*
@@ -438,15 +411,13 @@ setpgid(td, uap)
register struct setpgid_args *uap;
{
struct proc *curp = td->td_proc;
register struct proc *targp; /* target process */
register struct pgrp *pgrp; /* target pgrp */
register struct proc *targp; /* target process */
register struct pgrp *pgrp; /* target pgrp */
int error;
if (uap->pgid < 0)
return (EINVAL);
mtx_lock(&Giant);
sx_slock(&proctree_lock);
if (uap->pid != 0 && uap->pid != curp->p_pid) {
if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
@@ -479,11 +450,11 @@ setpgid(td, uap)
error = EPERM;
goto done2;
}
if (uap->pgid == 0) {
if (uap->pgid == 0)
uap->pgid = targp->p_pid;
} else if (uap->pgid != targp->p_pid) {
else if (uap->pgid != targp->p_pid) {
if ((pgrp = pgfind(uap->pgid)) == 0 ||
pgrp->pg_session != curp->p_session) {
pgrp->pg_session != curp->p_session) {
PROC_UNLOCK(targp);
error = EPERM;
goto done2;
@@ -527,16 +498,16 @@ setuid(td, uap)
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
uid_t uid;
int error = 0;
int error;
uid = uap->uid;
oldcred = p->p_ucred;
uid = uap->uid;
mtx_lock(&Giant);
error = 0;
/*
* See if we have "permission" by POSIX 1003.1 rules.
*
* Note that setuid(geteuid()) is a special case of
* Note that setuid(geteuid()) is a special case of
* "appropriate privileges" in appendix B.4.2.2. We need
* to use this clause to be compatible with traditional BSD
* semantics. Basically, it means that "setuid(xx)" sets all
@@ -546,7 +517,7 @@ setuid(td, uap)
* 1: We determine if the euid is going to change, and do EPERM
* right away. We unconditionally change the euid later if this
* test is satisfied, simplifying that part of the logic.
* 2: We determine if the real and/or saved uid's are going to
* 2: We determine if the real and/or saved uids are going to
* change. Determined by compile options.
* 3: Change euid last. (after tests in #2 for "appropriate privs")
*/
@@ -557,7 +528,7 @@ setuid(td, uap)
#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
uid != oldcred->cr_uid && /* allow setuid(geteuid()) */
#endif
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
goto done2;
newcred = crdup(oldcred);
@@ -625,17 +596,16 @@ seteuid(td, uap)
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
uid_t euid;
int error = 0;
int error;
euid = uap->euid;
mtx_lock(&Giant);
error = 0;
oldcred = p->p_ucred;
if (euid != oldcred->cr_ruid && /* allow seteuid(getuid()) */
euid != oldcred->cr_svuid && /* allow seteuid(saved uid) */
(error = suser_xxx(oldcred, NULL, PRISON_ROOT))) {
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
goto done2;
}
/*
* Everything's okay, do it. Copy credentials so other references do
* not see our changes.
@@ -669,11 +639,12 @@ setgid(td, uap)
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
gid_t gid;
int error = 0;
int error;
gid = uap->gid;
mtx_lock(&Giant);
error = 0;
oldcred = p->p_ucred;
/*
* See if we have "permission" by POSIX 1003.1 rules.
@@ -693,9 +664,8 @@ setgid(td, uap)
#ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */
gid != oldcred->cr_groups[0] && /* allow setgid(getegid()) */
#endif
(error = suser_xxx(oldcred, NULL, PRISON_ROOT))) {
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
goto done2;
}
newcred = crdup(oldcred);
#ifdef _POSIX_SAVED_IDS
@@ -761,17 +731,16 @@ setegid(td, uap)
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
gid_t egid;
int error = 0;
int error;
egid = uap->egid;
mtx_lock(&Giant);
error = 0;
oldcred = p->p_ucred;
if (egid != oldcred->cr_rgid && /* allow setegid(getgid()) */
egid != oldcred->cr_svgid && /* allow setegid(saved gid) */
(error = suser_xxx(oldcred, NULL, PRISON_ROOT))) {
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
goto done2;
}
newcred = crdup(oldcred);
if (oldcred->cr_groups[0] != egid) {
change_egid(newcred, egid);
@@ -805,10 +774,9 @@ setgroups(td, uap)
int error;
mtx_lock(&Giant);
ngrp = uap->gidsetsize;
oldcred = p->p_ucred;
if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)))
if ((error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
goto done2;
if (ngrp > NGROUPS) {
error = EINVAL;
@@ -860,22 +828,20 @@ setreuid(td, uap)
{
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
uid_t ruid, euid;
int error = 0;
uid_t euid, ruid;
int error;
ruid = uap->ruid;
euid = uap->euid;
ruid = uap->ruid;
mtx_lock(&Giant);
error = 0;
oldcred = p->p_ucred;
if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
ruid != oldcred->cr_svuid) ||
(euid != (uid_t)-1 && euid != oldcred->cr_uid &&
euid != oldcred->cr_ruid && euid != oldcred->cr_svuid)) &&
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) {
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
goto done2;
}
newcred = crdup(oldcred);
if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
change_euid(newcred, euid);
@@ -914,23 +880,20 @@ setregid(td, uap)
{
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
gid_t rgid, egid;
int error = 0;
gid_t egid, rgid;
int error;
rgid = uap->rgid;
egid = uap->egid;
rgid = uap->rgid;
mtx_lock(&Giant);
error = 0;
oldcred = p->p_ucred;
if (((rgid != (gid_t)-1 && rgid != oldcred->cr_rgid &&
rgid != oldcred->cr_svgid) ||
(egid != (gid_t)-1 && egid != oldcred->cr_groups[0] &&
egid != oldcred->cr_rgid && egid != oldcred->cr_svgid)) &&
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) {
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
goto done2;
}
newcred = crdup(oldcred);
if (egid != (gid_t)-1 && oldcred->cr_groups[0] != egid) {
change_egid(newcred, egid);
@@ -975,13 +938,12 @@ setresuid(td, uap)
{
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
uid_t ruid, euid, suid;
uid_t euid, ruid, suid;
int error;
ruid = uap->ruid;
euid = uap->euid;
ruid = uap->ruid;
suid = uap->suid;
mtx_lock(&Giant);
oldcred = p->p_ucred;
if (((ruid != (uid_t)-1 && ruid != oldcred->cr_ruid &&
@@ -993,10 +955,8 @@ setresuid(td, uap)
(suid != (uid_t)-1 && suid != oldcred->cr_ruid &&
suid != oldcred->cr_svuid &&
suid != oldcred->cr_uid)) &&
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0) {
(error = suser_xxx(oldcred, NULL, PRISON_ROOT)) != 0)
goto done2;
}
newcred = crdup(oldcred);
if (euid != (uid_t)-1 && oldcred->cr_uid != euid) {
change_euid(newcred, euid);
@@ -1041,11 +1001,11 @@ setresgid(td, uap)
{
struct proc *p = td->td_proc;
struct ucred *newcred, *oldcred;
gid_t rgid, egid, sgid;
gid_t egid, rgid, sgid;
int error;
rgid = uap->rgid;
egid = uap->egid;
rgid = uap->rgid;
sgid = uap->sgid;
mtx_lock(&Giant);
@@ -1105,7 +1065,6 @@ getresuid(td, uap)
mtx_lock(&Giant);
cred = p->p_ucred;
if (uap->ruid)
error1 = copyout((caddr_t)&cred->cr_ruid,
(caddr_t)uap->ruid, sizeof(cred->cr_ruid));
@@ -1116,7 +1075,7 @@ getresuid(td, uap)
error3 = copyout((caddr_t)&cred->cr_svuid,
(caddr_t)uap->suid, sizeof(cred->cr_svuid));
mtx_unlock(&Giant);
return error1 ? error1 : (error2 ? error2 : error3);
return (error1 ? error1 : error2 ? error2 : error3);
}
#ifndef _SYS_SYSPROTO_H_
@@ -1141,7 +1100,6 @@ getresgid(td, uap)
mtx_lock(&Giant);
cred = p->p_ucred;
if (uap->rgid)
error1 = copyout((caddr_t)&cred->cr_rgid,
(caddr_t)uap->rgid, sizeof(cred->cr_rgid));
@@ -1152,15 +1110,17 @@ getresgid(td, uap)
error3 = copyout((caddr_t)&cred->cr_svgid,
(caddr_t)uap->sgid, sizeof(cred->cr_svgid));
mtx_unlock(&Giant);
return error1 ? error1 : (error2 ? error2 : error3);
return (error1 ? error1 : error2 ? error2 : error3);
}
#ifndef _SYS_SYSPROTO_H_
struct issetugid_args {
int dummy;
};
#endif
/*
* NOT MPSAFE?
*/
/* ARGSUSED */
int
issetugid(td, uap)
@@ -1190,9 +1150,10 @@ __setugid(td, uap)
struct __setugid_args *uap;
{
#ifdef REGRESSION
int error = 0;
int error;
mtx_lock(&Giant);
error = 0;
switch (uap->flag) {
case 0:
td->td_proc->p_flag &= ~P_SUGID;
@@ -1207,8 +1168,9 @@ __setugid(td, uap)
mtx_unlock(&Giant);
return (error);
#else /* !REGRESSION */
return (ENOSYS);
#endif /* !REGRESSION */
#endif /* REGRESSION */
}
/*
@@ -1251,7 +1213,8 @@ int
suser(p)
struct proc *p;
{
return suser_xxx(0, p, 0);
return (suser_xxx(0, p, 0));
}
/*
@@ -1260,7 +1223,6 @@ suser(p)
*/
int
suser_td(td)
struct thread *td;
{
return suser_xxx(0, td->td_proc, 0);
@@ -1290,9 +1252,9 @@ suser_xxx(cred, proc, flag)
printf("suser_xxx(): THINK!\n");
return (EPERM);
}
if (!cred)
if (cred == NULL)
cred = proc->p_ucred;
if (cred->cr_uid != 0)
if (cred->cr_uid != 0)
return (EPERM);
if (jailed(cred) && !(flag & PRISON_ROOT))
return (EPERM);
@@ -1300,78 +1262,60 @@ suser_xxx(cred, proc, flag)
}
/*
* Test (local, globale) securelevel values against passed required
* securelevel. _gt implements (level > securelevel), and _ge implements
* (level >= securelevel). Returns 0 oer EPERM.
* Test the active securelevel against a given level. securelevel_gt()
* implements (securelevel > level). securelevel_ge() implements
* (securelevel >= level). Note that the logic is inverted -- these
* functions return EPERM on "success" and 0 on "failure".
*
* cr is permitted to be NULL for the time being, as there were some
* existing securelevel checks that occurred without a process/credential
* context. In the future this will be disallowed, so a kernel
* message is displayed.
* context. In the future this will be disallowed, so a kernel message
* is displayed.
*/
int
securelevel_gt(struct ucred *cr, int level)
{
int active_securelevel;
if (cr == NULL) {
active_securelevel = securelevel;
if (cr == NULL)
printf("securelevel_gt: cr is NULL\n");
if (level > securelevel)
return (0);
else
return (EPERM);
} else if (cr->cr_prison == NULL) {
if (level > securelevel)
return (0);
else
return (EPERM);
} else {
if (level > imax(cr->cr_prison->pr_securelevel, securelevel))
return (0);
else
return (EPERM);
}
if (cr->cr_prison != NULL)
active_securelevel = imax(cr->cr_prison->pr_securelevel,
active_securelevel);
return (active_securelevel > level ? EPERM : 0);
}
int
securelevel_ge(struct ucred *cr, int level)
{
int active_securelevel;
if (cr == NULL) {
printf("securelevel_ge: cr is NULL\n");
if (level >= securelevel)
return (0);
else
return (EPERM);
} if (cr->cr_prison == NULL) {
if (level >= securelevel)
return (0);
else
return (EPERM);
} else {
if (level >= imax(cr->cr_prison->pr_securelevel, securelevel))
return (0);
else
return (EPERM);
}
active_securelevel = securelevel;
if (cr == NULL)
printf("securelevel_gt: cr is NULL\n");
if (cr->cr_prison != NULL)
active_securelevel = imax(cr->cr_prison->pr_securelevel,
active_securelevel);
return (active_securelevel >= level ? EPERM : 0);
}
/*
* 'see_other_uids' determines whether or not visibility of processes
* and sockets with credentials holding different real uid's is possible
* and sockets with credentials holding different real uids is possible
* using a variety of system MIBs.
* XXX: data declarations should be together near the beginning of the file.
*/
static int see_other_uids = 1;
SYSCTL_INT(_kern_security_bsd, OID_AUTO, see_other_uids,
CTLFLAG_RW, &see_other_uids, 0,
SYSCTL_INT(_kern_security_bsd, OID_AUTO, see_other_uids, CTLFLAG_RW,
&see_other_uids, 0,
"Unprivileged processes may see subjects/objects with different real uid");
/*-
* Determine if u1 "can see" the subject specified by u2.
* Returns: 0 for permitted, an errno value otherwise
* Locks: none
* References: u1 and u2 must be immutable credentials
* u1 and u2 must be valid for the lifetime of the call
* References: *u1 and *u2 must not change during the call
* u1 may equal u2, in which case only one reference is required
*/
int
@@ -1480,11 +1424,11 @@ p_cansignal(struct proc *p1, struct proc *p2, int signum)
return (error);
}
return (0);
return (0);
}
/*-
* Determine whether p1 may reschedule p2
* Determine whether p1 may reschedule p2.
* Returns: 0 for permitted, an errno value otherwise
* Locks: Sufficient locks to protect various components of p1 and p2
* must be held. Normally, p1 will be curproc, and a lock must
@@ -1524,10 +1468,11 @@ p_cansched(struct proc *p1, struct proc *p2)
* when hardening systems.
*
* XXX: Should modifying and reading this variable require locking?
* XXX: data declarations should be together near the beginning of the file.
*/
static int unprivileged_proc_debug = 1;
SYSCTL_INT(_kern_security_bsd, OID_AUTO, unprivileged_proc_debug,
CTLFLAG_RW, &unprivileged_proc_debug, 0,
SYSCTL_INT(_kern_security_bsd, OID_AUTO, unprivileged_proc_debug, CTLFLAG_RW,
&unprivileged_proc_debug, 0,
"Unprivileged processes may use process debugging facilities");
/*-
@@ -1541,17 +1486,15 @@ SYSCTL_INT(_kern_security_bsd, OID_AUTO, unprivileged_proc_debug,
int
p_candebug(struct proc *p1, struct proc *p2)
{
int error, i, grpsubset, uidsubset, credentialchanged;
int credentialchanged, error, grpsubset, i, uidsubset;
if (!unprivileged_proc_debug) {
error = suser_xxx(NULL, p1, PRISON_ROOT);
if (error)
return (error);
}
if (p1 == p2)
return (0);
if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
return (error);
@@ -1595,8 +1538,8 @@ p_candebug(struct proc *p1, struct proc *p2)
return (error);
}
/* can't trace init when securelevel > 0 */
if (p2->p_pid == 1) {
/* Can't trace init when securelevel > 0. */
if (p2 == initproc) {
error = securelevel_gt(p1->p_ucred, 0);
if (error)
return (error);
@@ -1642,7 +1585,6 @@ crhold(cr)
return (cr);
}
/*
* Free a cred structure.
* Throws away space when ref count gets to 0.
@@ -1671,9 +1613,8 @@ crfree(cr)
if (jailed(cr))
prison_free(cr->cr_prison);
FREE((caddr_t)cr, M_CRED);
} else {
} else
mtx_unlock(&cr->cr_mtx);
}
}
/*
@@ -1701,7 +1642,7 @@ crcopy(dest, src)
KASSERT(crshared(dest) == 0, ("crcopy of shared ucred"));
bcopy(&src->cr_startcopy, &dest->cr_startcopy,
(unsigned)((caddr_t)&src->cr_endcopy -
(unsigned)((caddr_t)&src->cr_endcopy -
(caddr_t)&src->cr_startcopy));
uihold(dest->cr_uidinfo);
uihold(dest->cr_ruidinfo);
@@ -1775,16 +1716,15 @@ setlogin(td, uap)
char logintmp[MAXLOGNAME];
mtx_lock(&Giant);
if ((error = suser_xxx(0, p, PRISON_ROOT)))
if ((error = suser_xxx(0, p, PRISON_ROOT)) != 0)
goto done2;
error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp,
sizeof(logintmp), (size_t *)0);
if (error == ENAMETOOLONG) {
if (error == ENAMETOOLONG)
error = EINVAL;
} else if (!error) {
(void) memcpy(p->p_pgrp->pg_session->s_login, logintmp,
else if (!error)
(void)memcpy(p->p_pgrp->pg_session->s_login, logintmp,
sizeof(logintmp));
}
done2:
mtx_unlock(&Giant);
return (error);