nfsd: Continue adding macros so nfsd can run in a vnet prison

Commit 7344856e3a6d added a lot of macros that will front end
vnet macros so that nfsd(8) can run in vnet prison.
This patch adds some more, to allow the nfsuserd(8) daemon to
run in vnet prison, once the macros map to vnet ones.
This is the last commit for NFSD_VNET_xxx macros, but there are
still some for KRPC_VNET_xxx and KGSS_VNET_xx to allow the
rpc.tlsservd(8) and gssd(8) daemons to run in a vnet prison.

MFC after:	3 months
This commit is contained in:
Rick Macklem 2023-02-14 13:33:35 -08:00
parent 1bdf879b97
commit f0db2b6022
2 changed files with 169 additions and 134 deletions

View File

@ -56,8 +56,6 @@ __FBSDID("$FreeBSD$");
#include <vm/uma.h>
extern int nfscl_ticks;
extern nfsuserd_state nfsrv_nfsuserd;
extern struct nfssockreq nfsrv_nfsuserdsock;
extern void (*nfsd_call_recall)(struct vnode *, int, struct ucred *,
struct thread *);
extern int nfsrv_useacl;
@ -77,6 +75,9 @@ uint32_t nfs_srvmaxio = NFS_SRVMAXIO;
NFSD_VNET_DEFINE(struct nfsstatsv1 *, nfsstatsv1_p);
NFSD_VNET_DECLARE(struct nfssockreq, nfsrv_nfsuserdsock);
NFSD_VNET_DECLARE(nfsuserd_state, nfsrv_nfsuserd);
int nfs_pnfsio(task_fn_t *, void *);
static int nfs_realign_test;
@ -857,6 +858,7 @@ nfs_clean(struct prison *pr)
{
NFSD_CURVNET_SET(pr->pr_vnet);
mtx_destroy(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx);
if (pr != &prison0)
free(NFSD_VNET(nfsstatsv1_p), M_TEMP);
/* Clean out the name<-->id cache. */
@ -876,6 +878,8 @@ nfs_vnetinit(const void *unused __unused)
else
NFSD_VNET(nfsstatsv1_p) = malloc(sizeof(struct nfsstatsv1),
M_TEMP, M_WAITOK | M_ZERO);
mtx_init(&NFSD_VNET(nfsrv_nfsuserdsock).nr_mtx, "nfsuserd",
NULL, MTX_DEF);
}
SYSINIT(nfs_vnetinit, SI_SUB_VNET_DONE, SI_ORDER_ANY,
nfs_vnetinit, NULL);
@ -900,8 +904,6 @@ nfscommon_modevent(module_t mod, int type, void *data)
mtx_init(&nfs_sockl_mutex, "nfs_sockl_mutex", NULL, MTX_DEF);
mtx_init(&nfs_slock_mutex, "nfs_slock_mutex", NULL, MTX_DEF);
mtx_init(&nfs_req_mutex, "nfs_req_mutex", NULL, MTX_DEF);
mtx_init(&nfsrv_nfsuserdsock.nr_mtx, "nfsuserd", NULL,
MTX_DEF);
mtx_init(&nfsrv_dslock_mtx, "nfs4ds", NULL, MTX_DEF);
TAILQ_INIT(&nfsrv_devidhead);
newnfs_init();
@ -910,7 +912,8 @@ nfscommon_modevent(module_t mod, int type, void *data)
break;
case MOD_UNLOAD:
if (newnfs_numnfsd != 0 || nfsrv_nfsuserd != NOTRUNNING ||
if (newnfs_numnfsd != 0 ||
NFSD_VNET(nfsrv_nfsuserd) != NOTRUNNING ||
nfs_numnfscbd != 0) {
error = EBUSY;
break;
@ -926,7 +929,6 @@ nfscommon_modevent(module_t mod, int type, void *data)
mtx_destroy(&nfs_sockl_mutex);
mtx_destroy(&nfs_slock_mutex);
mtx_destroy(&nfs_req_mutex);
mtx_destroy(&nfsrv_nfsuserdsock.nr_mtx);
mtx_destroy(&nfsrv_dslock_mtx);
loaded = 0;
break;

View File

@ -66,17 +66,10 @@ enum vtype nv34tov_type[8]={ VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO };
struct timeval nfsboottime; /* Copy boottime once, so it never changes */
int nfscl_ticks;
int nfsrv_useacl = 1;
struct nfssockreq nfsrv_nfsuserdsock;
nfsuserd_state nfsrv_nfsuserd = NOTRUNNING;
static int nfsrv_userdupcalls = 0;
struct nfsreqhead nfsd_reqq;
uid_t nfsrv_defaultuid = UID_NOBODY;
gid_t nfsrv_defaultgid = GID_NOGROUP;
int nfsrv_lease = NFSRV_LEASE;
int ncl_mbuf_mlen = MLEN;
int nfsd_enable_stringtouid = 0;
int nfsrv_doflexfile = 0;
static int nfs_enable_uidtostring = 0;
NFSNAMEIDMUTEX;
NFSSOCKMUTEX;
extern int nfsrv_lughashsize;
@ -87,9 +80,20 @@ extern struct nfsdevicehead nfsrv_devidhead;
extern struct nfsstatsv1 nfsstatsv1;
extern uint32_t nfs_srvmaxio;
NFSD_VNET_DEFINE(int, nfsd_enable_stringtouid) = 0;
NFSD_VNET_DEFINE(struct nfssockreq, nfsrv_nfsuserdsock);
NFSD_VNET_DEFINE(nfsuserd_state, nfsrv_nfsuserd) = NOTRUNNING;
NFSD_VNET_DEFINE(uid_t, nfsrv_defaultuid) = UID_NOBODY;
NFSD_VNET_DEFINE(gid_t, nfsrv_defaultgid) = GID_NOGROUP;
NFSD_VNET_DEFINE_STATIC(int, nfsrv_userdupcalls) = 0;
SYSCTL_DECL(_vfs_nfs);
SYSCTL_INT(_vfs_nfs, OID_AUTO, enable_uidtostring, CTLFLAG_RW,
&nfs_enable_uidtostring, 0, "Make nfs always send numeric owner_names");
NFSD_VNET_DEFINE_STATIC(int, nfs_enable_uidtostring) = 0;
SYSCTL_INT(_vfs_nfs, OID_AUTO, enable_uidtostring,
CTLFLAG_NFSD_VNET | CTLFLAG_RW, &NFSD_VNET_NAME(nfs_enable_uidtostring), 0,
"Make nfs always send numeric owner_names");
int nfsrv_maxpnfsmirror = 1;
SYSCTL_INT(_vfs_nfs, OID_AUTO, pnfsmirror, CTLFLAG_RD,
@ -192,18 +196,19 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
};
static int ncl_mbuf_mhlen = MHLEN;
static int nfsrv_usercnt = 0;
static int nfsrv_dnsnamelen;
static u_char *nfsrv_dnsname = NULL;
static int nfsrv_usermax = 999999999;
struct nfsrv_lughash {
struct mtx mtx;
struct nfsuserhashhead lughead;
};
static struct nfsrv_lughash *nfsuserhash;
static struct nfsrv_lughash *nfsusernamehash;
static struct nfsrv_lughash *nfsgrouphash;
static struct nfsrv_lughash *nfsgroupnamehash;
NFSD_VNET_DEFINE_STATIC(int, nfsrv_usercnt) = 0;
NFSD_VNET_DEFINE_STATIC(int, nfsrv_dnsnamelen) = 0;
NFSD_VNET_DEFINE_STATIC(int, nfsrv_usermax) = 999999999;
NFSD_VNET_DEFINE_STATIC(struct nfsrv_lughash *, nfsuserhash) = NULL;
NFSD_VNET_DEFINE_STATIC(struct nfsrv_lughash *, nfsusernamehash) = NULL;
NFSD_VNET_DEFINE_STATIC(struct nfsrv_lughash *, nfsgrouphash) = NULL;
NFSD_VNET_DEFINE_STATIC(struct nfsrv_lughash *, nfsgroupnamehash) = NULL;
NFSD_VNET_DEFINE_STATIC(u_char *, nfsrv_dnsname) = NULL;
/*
* This static array indicates whether or not the RPC generates a large
@ -1245,6 +1250,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
#endif
CTASSERT(sizeof(ino_t) == sizeof(uint64_t));
NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread));
if (compare) {
retnotsup = 0;
error = nfsrv_getattrbits(nd, &attrbits, NULL, &retnotsup);
@ -1870,7 +1876,8 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
}
} else if (nap != NULL) {
if (nfsv4_strtouid(nd, cp, j, &uid))
nap->na_uid = nfsrv_defaultuid;
nap->na_uid =
NFSD_VNET(nfsrv_defaultuid);
else
nap->na_uid = uid;
}
@ -1903,7 +1910,8 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
}
} else if (nap != NULL) {
if (nfsv4_strtogid(nd, cp, j, &gid))
nap->na_gid = nfsrv_defaultgid;
nap->na_gid =
NFSD_VNET(nfsrv_defaultgid);
else
nap->na_gid = gid;
}
@ -2266,6 +2274,7 @@ nfsv4_loadattr(struct nfsrv_descript *nd, vnode_t vp,
error = nfsm_advance(nd, attrsize - attrsum, -1);
}
nfsmout:
NFSD_CURVNET_RESTORE();
NFSEXITCODE2(error, nd);
return (error);
}
@ -3142,14 +3151,16 @@ nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp)
int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
struct nfsrv_lughash *hp;
NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread));
cnt = 0;
tryagain:
if (nfsrv_dnsnamelen > 0 && !nfs_enable_uidtostring) {
if (NFSD_VNET(nfsrv_dnsnamelen) > 0 &&
!NFSD_VNET(nfs_enable_uidtostring)) {
/*
* Always map nfsrv_defaultuid to "nobody".
*/
if (uid == nfsrv_defaultuid) {
i = nfsrv_dnsnamelen + 7;
if (uid == NFSD_VNET(nfsrv_defaultuid)) {
i = NFSD_VNET(nfsrv_dnsnamelen) + 7;
if (i > len) {
if (len > NFSV4_SMALLSTR)
free(cp, M_NFSSTRING);
@ -3161,7 +3172,9 @@ nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp)
*retlenp = i;
NFSBCOPY("nobody@", cp, 7);
cp += 7;
NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
NFSBCOPY(NFSD_VNET(nfsrv_dnsname), cp,
NFSD_VNET(nfsrv_dnsnamelen));
NFSD_CURVNET_RESTORE();
return;
}
hasampersand = 0;
@ -3185,7 +3198,7 @@ nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp)
i = usrp->lug_namelen;
else
i = usrp->lug_namelen +
nfsrv_dnsnamelen + 1;
NFSD_VNET(nfsrv_dnsnamelen) + 1;
if (i > len) {
mtx_unlock(&hp->mtx);
if (len > NFSV4_SMALLSTR)
@ -3200,12 +3213,14 @@ nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp)
if (!hasampersand) {
cp += usrp->lug_namelen;
*cp++ = '@';
NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
NFSBCOPY(NFSD_VNET(nfsrv_dnsname), cp,
NFSD_VNET(nfsrv_dnsnamelen));
}
TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
TAILQ_INSERT_TAIL(&hp->lughead, usrp,
lug_numhash);
mtx_unlock(&hp->mtx);
NFSD_CURVNET_RESTORE();
return;
}
}
@ -3233,6 +3248,7 @@ nfsv4_uidtostr(uid_t uid, u_char **cpp, int *retlenp)
*cp-- = '0' + (tmp % 10);
tmp /= 10;
}
NFSD_CURVNET_RESTORE();
return;
}
@ -3253,7 +3269,7 @@ nfsrv_getgrpscred(struct ucred *oldcred)
cnt = 0;
uid = oldcred->cr_uid;
tryagain:
if (nfsrv_dnsnamelen > 0) {
if (NFSD_VNET(nfsrv_dnsnamelen) > 0) {
hp = NFSUSERHASH(uid);
mtx_lock(&hp->mtx);
TAILQ_FOREACH(usrp, &hp->lughead, lug_numhash) {
@ -3300,6 +3316,7 @@ nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp)
uid_t tuid;
struct nfsrv_lughash *hp, *hp2;
NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread));
if (len == 0) {
error = NFSERR_BADOWNER;
goto out;
@ -3311,7 +3328,7 @@ nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp)
/* A numeric string. */
if ((nd->nd_flag & ND_KERBV) == 0 &&
((nd->nd_flag & ND_NFSCL) != 0 ||
nfsd_enable_stringtouid != 0))
NFSD_VNET(nfsd_enable_stringtouid) != 0))
*uidp = tuid;
else
error = NFSERR_BADOWNER;
@ -3328,7 +3345,7 @@ nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp)
cnt = 0;
tryagain:
if (nfsrv_dnsnamelen > 0) {
if (NFSD_VNET(nfsrv_dnsnamelen) > 0) {
/*
* If an '@' is found and the domain name matches, search for
* the name with dns stripped off.
@ -3336,9 +3353,10 @@ nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp)
* all upper case will not.
*/
if (cnt == 0 && i < len && i > 0 &&
(len - 1 - i) == nfsrv_dnsnamelen &&
!nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
len -= (nfsrv_dnsnamelen + 1);
(len - 1 - i) == NFSD_VNET(nfsrv_dnsnamelen) &&
!nfsrv_cmpmixedcase(cp,
NFSD_VNET(nfsrv_dnsname), NFSD_VNET(nfsrv_dnsnamelen))) {
len -= (NFSD_VNET(nfsrv_dnsnamelen) + 1);
*(cp - 1) = '\0';
}
@ -3346,7 +3364,7 @@ nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp)
* Check for the special case of "nobody".
*/
if (len == 6 && !NFSBCMP(str, "nobody", 6)) {
*uidp = nfsrv_defaultuid;
*uidp = NFSD_VNET(nfsrv_defaultuid);
error = 0;
goto out;
}
@ -3380,6 +3398,7 @@ nfsv4_strtouid(struct nfsrv_descript *nd, u_char *str, int len, uid_t *uidp)
error = NFSERR_BADOWNER;
out:
NFSD_CURVNET_RESTORE();
NFSEXITCODE(error);
return (error);
}
@ -3401,14 +3420,16 @@ nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp)
int cnt, hasampersand, len = NFSV4_SMALLSTR, ret;
struct nfsrv_lughash *hp;
NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread));
cnt = 0;
tryagain:
if (nfsrv_dnsnamelen > 0 && !nfs_enable_uidtostring) {
if (NFSD_VNET(nfsrv_dnsnamelen) > 0 &&
!NFSD_VNET(nfs_enable_uidtostring)) {
/*
* Always map nfsrv_defaultgid to "nogroup".
*/
if (gid == nfsrv_defaultgid) {
i = nfsrv_dnsnamelen + 8;
if (gid == NFSD_VNET(nfsrv_defaultgid)) {
i = NFSD_VNET(nfsrv_dnsnamelen) + 8;
if (i > len) {
if (len > NFSV4_SMALLSTR)
free(cp, M_NFSSTRING);
@ -3420,7 +3441,9 @@ nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp)
*retlenp = i;
NFSBCOPY("nogroup@", cp, 8);
cp += 8;
NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
NFSBCOPY(NFSD_VNET(nfsrv_dnsname), cp,
NFSD_VNET(nfsrv_dnsnamelen));
NFSD_CURVNET_RESTORE();
return;
}
hasampersand = 0;
@ -3444,7 +3467,7 @@ nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp)
i = usrp->lug_namelen;
else
i = usrp->lug_namelen +
nfsrv_dnsnamelen + 1;
NFSD_VNET(nfsrv_dnsnamelen) + 1;
if (i > len) {
mtx_unlock(&hp->mtx);
if (len > NFSV4_SMALLSTR)
@ -3459,12 +3482,14 @@ nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp)
if (!hasampersand) {
cp += usrp->lug_namelen;
*cp++ = '@';
NFSBCOPY(nfsrv_dnsname, cp, nfsrv_dnsnamelen);
NFSBCOPY(NFSD_VNET(nfsrv_dnsname), cp,
NFSD_VNET(nfsrv_dnsnamelen));
}
TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
TAILQ_INSERT_TAIL(&hp->lughead, usrp,
lug_numhash);
mtx_unlock(&hp->mtx);
NFSD_CURVNET_RESTORE();
return;
}
}
@ -3492,6 +3517,7 @@ nfsv4_gidtostr(gid_t gid, u_char **cpp, int *retlenp)
*cp-- = '0' + (tmp % 10);
tmp /= 10;
}
NFSD_CURVNET_RESTORE();
return;
}
@ -3514,6 +3540,7 @@ nfsv4_strtogid(struct nfsrv_descript *nd, u_char *str, int len, gid_t *gidp)
gid_t tgid;
struct nfsrv_lughash *hp, *hp2;
NFSD_CURVNET_SET_QUIET(NFSD_TD_TO_VNET(curthread));
if (len == 0) {
error = NFSERR_BADOWNER;
goto out;
@ -3525,7 +3552,7 @@ nfsv4_strtogid(struct nfsrv_descript *nd, u_char *str, int len, gid_t *gidp)
/* A numeric string. */
if ((nd->nd_flag & ND_KERBV) == 0 &&
((nd->nd_flag & ND_NFSCL) != 0 ||
nfsd_enable_stringtouid != 0))
NFSD_VNET(nfsd_enable_stringtouid) != 0))
*gidp = tgid;
else
error = NFSERR_BADOWNER;
@ -3542,15 +3569,16 @@ nfsv4_strtogid(struct nfsrv_descript *nd, u_char *str, int len, gid_t *gidp)
cnt = 0;
tryagain:
if (nfsrv_dnsnamelen > 0) {
if (NFSD_VNET(nfsrv_dnsnamelen) > 0) {
/*
* If an '@' is found and the dns name matches, search for the
* name with the dns stripped off.
*/
if (cnt == 0 && i < len && i > 0 &&
(len - 1 - i) == nfsrv_dnsnamelen &&
!nfsrv_cmpmixedcase(cp, nfsrv_dnsname, nfsrv_dnsnamelen)) {
len -= (nfsrv_dnsnamelen + 1);
(len - 1 - i) == NFSD_VNET(nfsrv_dnsnamelen) &&
!nfsrv_cmpmixedcase(cp,
NFSD_VNET(nfsrv_dnsname), NFSD_VNET(nfsrv_dnsnamelen))) {
len -= (NFSD_VNET(nfsrv_dnsnamelen) + 1);
*(cp - 1) = '\0';
}
@ -3558,7 +3586,7 @@ nfsv4_strtogid(struct nfsrv_descript *nd, u_char *str, int len, gid_t *gidp)
* Check for the special case of "nogroup".
*/
if (len == 7 && !NFSBCMP(str, "nogroup", 7)) {
*gidp = nfsrv_defaultgid;
*gidp = NFSD_VNET(nfsrv_defaultgid);
error = 0;
goto out;
}
@ -3592,6 +3620,7 @@ nfsv4_strtogid(struct nfsrv_descript *nd, u_char *str, int len, gid_t *gidp)
error = NFSERR_BADOWNER;
out:
NFSD_CURVNET_RESTORE();
NFSEXITCODE(error);
return (error);
}
@ -3642,12 +3671,12 @@ nfsrv_nfsuserdport(struct nfsuserd_args *nargs, NFSPROC_T *p)
int error;
NFSLOCKNAMEID();
if (nfsrv_nfsuserd != NOTRUNNING) {
if (NFSD_VNET(nfsrv_nfsuserd) != NOTRUNNING) {
NFSUNLOCKNAMEID();
error = EPERM;
goto out;
}
nfsrv_nfsuserd = STARTSTOP;
NFSD_VNET(nfsrv_nfsuserd) = STARTSTOP;
/*
* Set up the socket record and connect.
* Set nr_client NULL before unlocking, just to ensure that no other
@ -3655,7 +3684,7 @@ nfsrv_nfsuserdport(struct nfsuserd_args *nargs, NFSPROC_T *p)
* occur if the use of the nameid lock to protect nfsrv_nfsuserd is
* broken.
*/
rp = &nfsrv_nfsuserdsock;
rp = &NFSD_VNET(nfsrv_nfsuserdsock);
rp->nr_client = NULL;
NFSUNLOCKNAMEID();
rp->nr_sotype = SOCK_DGRAM;
@ -3696,12 +3725,12 @@ nfsrv_nfsuserdport(struct nfsuserd_args *nargs, NFSPROC_T *p)
&rp->nr_client);
if (error == 0) {
NFSLOCKNAMEID();
nfsrv_nfsuserd = RUNNING;
NFSD_VNET(nfsrv_nfsuserd) = RUNNING;
NFSUNLOCKNAMEID();
} else {
free(rp->nr_nam, M_SONAME);
NFSLOCKNAMEID();
nfsrv_nfsuserd = NOTRUNNING;
NFSD_VNET(nfsrv_nfsuserd) = NOTRUNNING;
NFSUNLOCKNAMEID();
}
out:
@ -3717,20 +3746,20 @@ nfsrv_nfsuserddelport(void)
{
NFSLOCKNAMEID();
if (nfsrv_nfsuserd != RUNNING) {
if (NFSD_VNET(nfsrv_nfsuserd) != RUNNING) {
NFSUNLOCKNAMEID();
return;
}
nfsrv_nfsuserd = STARTSTOP;
NFSD_VNET(nfsrv_nfsuserd) = STARTSTOP;
/* Wait for all upcalls to complete. */
while (nfsrv_userdupcalls > 0)
msleep(&nfsrv_userdupcalls, NFSNAMEIDMUTEXPTR, PVFS,
while (NFSD_VNET(nfsrv_userdupcalls) > 0)
msleep(&NFSD_VNET(nfsrv_userdupcalls), NFSNAMEIDMUTEXPTR, PVFS,
"nfsupcalls", 0);
NFSUNLOCKNAMEID();
newnfs_disconnect(NULL, &nfsrv_nfsuserdsock);
free(nfsrv_nfsuserdsock.nr_nam, M_SONAME);
newnfs_disconnect(NULL, &NFSD_VNET(nfsrv_nfsuserdsock));
free(NFSD_VNET(nfsrv_nfsuserdsock).nr_nam, M_SONAME);
NFSLOCKNAMEID();
nfsrv_nfsuserd = NOTRUNNING;
NFSD_VNET(nfsrv_nfsuserd) = NOTRUNNING;
NFSUNLOCKNAMEID();
}
@ -3750,7 +3779,7 @@ nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name)
int error;
NFSLOCKNAMEID();
if (nfsrv_nfsuserd != RUNNING) {
if (NFSD_VNET(nfsrv_nfsuserd) != RUNNING) {
NFSUNLOCKNAMEID();
error = EPERM;
goto out;
@ -3759,9 +3788,9 @@ nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name)
* Maintain a count of upcalls in progress, so that nfsrv_X()
* can wait until no upcalls are in progress.
*/
nfsrv_userdupcalls++;
NFSD_VNET(nfsrv_userdupcalls)++;
NFSUNLOCKNAMEID();
KASSERT(nfsrv_userdupcalls > 0,
KASSERT(NFSD_VNET(nfsrv_userdupcalls) > 0,
("nfsrv_getuser: non-positive upcalls"));
nd = &nfsd;
cred = newnfs_getcred();
@ -3779,11 +3808,13 @@ nfsrv_getuser(int procnum, uid_t uid, gid_t gid, char *name)
len = strlen(name);
(void) nfsm_strtom(nd, name, len);
}
error = newnfs_request(nd, NULL, NULL, &nfsrv_nfsuserdsock, NULL, NULL,
cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0, NULL, NULL);
error = newnfs_request(nd, NULL, NULL, &NFSD_VNET(nfsrv_nfsuserdsock),
NULL, NULL, cred, RPCPROG_NFSUSERD, RPCNFSUSERD_VERS, NULL, 0,
NULL, NULL);
NFSLOCKNAMEID();
if (--nfsrv_userdupcalls == 0 && nfsrv_nfsuserd == STARTSTOP)
wakeup(&nfsrv_userdupcalls);
if (--NFSD_VNET(nfsrv_userdupcalls) == 0 &&
NFSD_VNET(nfsrv_nfsuserd) == STARTSTOP)
wakeup(&NFSD_VNET(nfsrv_userdupcalls));
NFSUNLOCKNAMEID();
NFSFREECRED(cred);
if (!error) {
@ -3823,7 +3854,8 @@ nfssvc_idname(struct nfsd_idargs *nidp)
free(cp, M_NFSSTRING);
goto out;
}
if (atomic_cmpset_acq_int(&nfsrv_dnsnamelen, 0, 0) == 0) {
if (atomic_cmpset_acq_int(&NFSD_VNET(nfsrv_dnsnamelen), 0, 0) ==
0) {
/*
* Free up all the old stuff and reinitialize hash
* lists. All mutexes for both lists must be locked,
@ -3831,80 +3863,81 @@ nfssvc_idname(struct nfsd_idargs *nidp)
* ones, to avoid a LOR.
*/
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsusernamehash[i].mtx);
mtx_lock(&NFSD_VNET(nfsusernamehash)[i].mtx);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsuserhash[i].mtx);
mtx_lock(&NFSD_VNET(nfsuserhash)[i].mtx);
for (i = 0; i < nfsrv_lughashsize; i++)
TAILQ_FOREACH_SAFE(usrp,
&nfsuserhash[i].lughead, lug_numhash, nusrp)
&NFSD_VNET(nfsuserhash)[i].lughead, lug_numhash, nusrp)
nfsrv_removeuser(usrp, 1);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_unlock(&nfsuserhash[i].mtx);
mtx_unlock(&NFSD_VNET(nfsuserhash)[i].mtx);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_unlock(&nfsusernamehash[i].mtx);
mtx_unlock(&NFSD_VNET(nfsusernamehash)[i].mtx);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsgroupnamehash[i].mtx);
mtx_lock(&NFSD_VNET(nfsgroupnamehash)[i].mtx);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsgrouphash[i].mtx);
mtx_lock(&NFSD_VNET(nfsgrouphash)[i].mtx);
for (i = 0; i < nfsrv_lughashsize; i++)
TAILQ_FOREACH_SAFE(usrp,
&nfsgrouphash[i].lughead, lug_numhash,
&NFSD_VNET(nfsgrouphash)[i].lughead, lug_numhash,
nusrp)
nfsrv_removeuser(usrp, 0);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_unlock(&nfsgrouphash[i].mtx);
mtx_unlock(&NFSD_VNET(nfsgrouphash)[i].mtx);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_unlock(&nfsgroupnamehash[i].mtx);
free(nfsrv_dnsname, M_NFSSTRING);
nfsrv_dnsname = NULL;
mtx_unlock(&NFSD_VNET(nfsgroupnamehash)[i].mtx);
free(NFSD_VNET(nfsrv_dnsname), M_NFSSTRING);
NFSD_VNET(nfsrv_dnsname) = NULL;
}
if (nfsuserhash == NULL) {
if (NFSD_VNET(nfsuserhash) == NULL) {
/* Allocate the hash tables. */
nfsuserhash = malloc(sizeof(struct nfsrv_lughash) *
NFSD_VNET(nfsuserhash) = malloc(sizeof(struct nfsrv_lughash) *
nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
M_ZERO);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_init(&nfsuserhash[i].mtx, "nfsuidhash",
mtx_init(&NFSD_VNET(nfsuserhash)[i].mtx, "nfsuidhash",
NULL, MTX_DEF | MTX_DUPOK);
nfsusernamehash = malloc(sizeof(struct nfsrv_lughash) *
NFSD_VNET(nfsusernamehash) = malloc(sizeof(struct nfsrv_lughash) *
nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
M_ZERO);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_init(&nfsusernamehash[i].mtx,
mtx_init(&NFSD_VNET(nfsusernamehash)[i].mtx,
"nfsusrhash", NULL, MTX_DEF |
MTX_DUPOK);
nfsgrouphash = malloc(sizeof(struct nfsrv_lughash) *
NFSD_VNET(nfsgrouphash) = malloc(sizeof(struct nfsrv_lughash) *
nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
M_ZERO);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_init(&nfsgrouphash[i].mtx, "nfsgidhash",
mtx_init(&NFSD_VNET(nfsgrouphash)[i].mtx, "nfsgidhash",
NULL, MTX_DEF | MTX_DUPOK);
nfsgroupnamehash = malloc(sizeof(struct nfsrv_lughash) *
NFSD_VNET(nfsgroupnamehash) = malloc(sizeof(struct nfsrv_lughash) *
nfsrv_lughashsize, M_NFSUSERGROUP, M_WAITOK |
M_ZERO);
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_init(&nfsgroupnamehash[i].mtx,
mtx_init(&NFSD_VNET(nfsgroupnamehash)[i].mtx,
"nfsgrphash", NULL, MTX_DEF | MTX_DUPOK);
}
/* (Re)initialize the list heads. */
for (i = 0; i < nfsrv_lughashsize; i++)
TAILQ_INIT(&nfsuserhash[i].lughead);
TAILQ_INIT(&NFSD_VNET(nfsuserhash)[i].lughead);
for (i = 0; i < nfsrv_lughashsize; i++)
TAILQ_INIT(&nfsusernamehash[i].lughead);
TAILQ_INIT(&NFSD_VNET(nfsusernamehash)[i].lughead);
for (i = 0; i < nfsrv_lughashsize; i++)
TAILQ_INIT(&nfsgrouphash[i].lughead);
TAILQ_INIT(&NFSD_VNET(nfsgrouphash)[i].lughead);
for (i = 0; i < nfsrv_lughashsize; i++)
TAILQ_INIT(&nfsgroupnamehash[i].lughead);
TAILQ_INIT(&NFSD_VNET(nfsgroupnamehash)[i].lughead);
/*
* Put name in "DNS" string.
*/
nfsrv_dnsname = cp;
nfsrv_defaultuid = nidp->nid_uid;
nfsrv_defaultgid = nidp->nid_gid;
nfsrv_usercnt = 0;
nfsrv_usermax = nidp->nid_usermax;
atomic_store_rel_int(&nfsrv_dnsnamelen, nidp->nid_namelen);
NFSD_VNET(nfsrv_dnsname) = cp;
NFSD_VNET(nfsrv_defaultuid) = nidp->nid_uid;
NFSD_VNET(nfsrv_defaultgid) = nidp->nid_gid;
NFSD_VNET(nfsrv_usercnt) = 0;
NFSD_VNET(nfsrv_usermax) = nidp->nid_usermax;
atomic_store_rel_int(&NFSD_VNET(nfsrv_dnsnamelen),
nidp->nid_namelen);
goto out;
}
@ -3931,7 +3964,7 @@ nfssvc_idname(struct nfsd_idargs *nidp)
cr->cr_uid = cr->cr_ruid = cr->cr_svuid = nidp->nid_uid;
crsetgroups(cr, nidp->nid_ngroup, grps);
cr->cr_rgid = cr->cr_svgid = cr->cr_groups[0];
cr->cr_prison = &prison0;
cr->cr_prison = curthread->td_ucred->cr_prison;
prison_hold(cr->cr_prison);
#ifdef MAC
mac_cred_associate_nfsd(cr);
@ -3963,7 +3996,7 @@ nfssvc_idname(struct nfsd_idargs *nidp)
if (nidp->nid_flag & (NFSID_DELUID | NFSID_ADDUID)) {
/* Must lock all username hash lists first, to avoid a LOR. */
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsusernamehash[i].mtx);
mtx_lock(&NFSD_VNET(nfsusernamehash)[i].mtx);
username_locked = 1;
hp_idnum = NFSUSERHASH(nidp->nid_uid);
mtx_lock(&hp_idnum->mtx);
@ -3992,7 +4025,7 @@ nfssvc_idname(struct nfsd_idargs *nidp)
} else if (nidp->nid_flag & (NFSID_DELGID | NFSID_ADDGID)) {
/* Must lock all groupname hash lists first, to avoid a LOR. */
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsgroupnamehash[i].mtx);
mtx_lock(&NFSD_VNET(nfsgroupnamehash)[i].mtx);
groupname_locked = 1;
hp_idnum = NFSGROUPHASH(nidp->nid_gid);
mtx_lock(&hp_idnum->mtx);
@ -4035,7 +4068,7 @@ nfssvc_idname(struct nfsd_idargs *nidp)
thp = NFSUSERNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
mtx_assert(&thp->mtx, MA_OWNED);
TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_namehash);
atomic_add_int(&nfsrv_usercnt, 1);
atomic_add_int(&NFSD_VNET(nfsrv_usercnt), 1);
} else if (nidp->nid_flag & (NFSID_ADDGID | NFSID_ADDGROUPNAME)) {
newusrp->lug_gid = nidp->nid_gid;
thp = NFSGROUPHASH(newusrp->lug_gid);
@ -4044,7 +4077,7 @@ nfssvc_idname(struct nfsd_idargs *nidp)
thp = NFSGROUPNAMEHASH(newusrp->lug_name, newusrp->lug_namelen);
mtx_assert(&thp->mtx, MA_OWNED);
TAILQ_INSERT_TAIL(&thp->lughead, newusrp, lug_namehash);
atomic_add_int(&nfsrv_usercnt, 1);
atomic_add_int(&NFSD_VNET(nfsrv_usercnt), 1);
} else {
if (newusrp->lug_cred != NULL)
crfree(newusrp->lug_cred);
@ -4073,17 +4106,17 @@ nfssvc_idname(struct nfsd_idargs *nidp)
NFSID_DELUSERNAME | NFSID_ADDUSERNAME)) != 0) {
if (username_locked == 0) {
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsusernamehash[i].mtx);
mtx_lock(&NFSD_VNET(nfsusernamehash)[i].mtx);
username_locked = 1;
}
KASSERT(user_locked == 0,
("nfssvc_idname: user_locked"));
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsuserhash[i].mtx);
mtx_lock(&NFSD_VNET(nfsuserhash)[i].mtx);
user_locked = 1;
for (i = 0; i < nfsrv_lughashsize; i++) {
TAILQ_FOREACH_SAFE(usrp,
&nfsuserhash[i].lughead, lug_numhash,
&NFSD_VNET(nfsuserhash)[i].lughead, lug_numhash,
nusrp)
if (usrp->lug_expiry < NFSD_MONOSEC)
nfsrv_removeuser(usrp, 1);
@ -4094,26 +4127,26 @@ nfssvc_idname(struct nfsd_idargs *nidp)
* algorithm. This code deletes the least
* recently used entry on each hash list.
*/
if (nfsrv_usercnt <= nfsrv_usermax)
if (NFSD_VNET(nfsrv_usercnt) <= NFSD_VNET(nfsrv_usermax))
break;
usrp = TAILQ_FIRST(&nfsuserhash[i].lughead);
usrp = TAILQ_FIRST(&NFSD_VNET(nfsuserhash)[i].lughead);
if (usrp != NULL)
nfsrv_removeuser(usrp, 1);
}
} else {
if (groupname_locked == 0) {
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsgroupnamehash[i].mtx);
mtx_lock(&NFSD_VNET(nfsgroupnamehash)[i].mtx);
groupname_locked = 1;
}
KASSERT(group_locked == 0,
("nfssvc_idname: group_locked"));
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_lock(&nfsgrouphash[i].mtx);
mtx_lock(&NFSD_VNET(nfsgrouphash)[i].mtx);
group_locked = 1;
for (i = 0; i < nfsrv_lughashsize; i++) {
TAILQ_FOREACH_SAFE(usrp,
&nfsgrouphash[i].lughead, lug_numhash,
&NFSD_VNET(nfsgrouphash)[i].lughead, lug_numhash,
nusrp)
if (usrp->lug_expiry < NFSD_MONOSEC)
nfsrv_removeuser(usrp, 0);
@ -4124,9 +4157,9 @@ nfssvc_idname(struct nfsd_idargs *nidp)
* algorithm. This code deletes the least
* recently user entry on each hash list.
*/
if (nfsrv_usercnt <= nfsrv_usermax)
if (NFSD_VNET(nfsrv_usercnt) <= NFSD_VNET(nfsrv_usermax))
break;
usrp = TAILQ_FIRST(&nfsgrouphash[i].lughead);
usrp = TAILQ_FIRST(&NFSD_VNET(nfsgrouphash)[i].lughead);
if (usrp != NULL)
nfsrv_removeuser(usrp, 0);
}
@ -4142,16 +4175,16 @@ nfssvc_idname(struct nfsd_idargs *nidp)
mtx_unlock(&hp_name->mtx);
if (user_locked != 0)
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_unlock(&nfsuserhash[i].mtx);
mtx_unlock(&NFSD_VNET(nfsuserhash)[i].mtx);
if (username_locked != 0)
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_unlock(&nfsusernamehash[i].mtx);
mtx_unlock(&NFSD_VNET(nfsusernamehash)[i].mtx);
if (group_locked != 0)
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_unlock(&nfsgrouphash[i].mtx);
mtx_unlock(&NFSD_VNET(nfsgrouphash)[i].mtx);
if (groupname_locked != 0)
for (i = 0; i < nfsrv_lughashsize; i++)
mtx_unlock(&nfsgroupnamehash[i].mtx);
mtx_unlock(&NFSD_VNET(nfsgroupnamehash)[i].mtx);
out:
NFSEXITCODE(error);
return (error);
@ -4180,7 +4213,7 @@ nfsrv_removeuser(struct nfsusrgrp *usrp, int isuser)
mtx_assert(&hp->mtx, MA_OWNED);
TAILQ_REMOVE(&hp->lughead, usrp, lug_namehash);
}
atomic_add_int(&nfsrv_usercnt, -1);
atomic_add_int(&NFSD_VNET(nfsrv_usercnt), -1);
if (usrp->lug_cred != NULL)
crfree(usrp->lug_cred);
free(usrp, M_NFSUSERGROUP);
@ -4190,7 +4223,7 @@ nfsrv_removeuser(struct nfsusrgrp *usrp, int isuser)
* Free up all the allocations related to the name<-->id cache.
* This function should only be called when the nfsuserd daemon isn't
* running, since it doesn't do any locking.
* This function is meant to be used when the nfscommon module is unloaded.
* This function is meant to be called when a vnet jail is destroyed.
*/
void
nfsrv_cleanusergroup(void)
@ -4199,11 +4232,11 @@ nfsrv_cleanusergroup(void)
struct nfsusrgrp *nusrp, *usrp;
int i;
if (nfsuserhash == NULL)
if (NFSD_VNET(nfsuserhash) == NULL)
return;
for (i = 0; i < nfsrv_lughashsize; i++) {
hp = &nfsuserhash[i];
hp = &NFSD_VNET(nfsuserhash)[i];
TAILQ_FOREACH_SAFE(usrp, &hp->lughead, lug_numhash, nusrp) {
TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
hp2 = NFSUSERNAMEHASH(usrp->lug_name,
@ -4213,7 +4246,7 @@ nfsrv_cleanusergroup(void)
crfree(usrp->lug_cred);
free(usrp, M_NFSUSERGROUP);
}
hp = &nfsgrouphash[i];
hp = &NFSD_VNET(nfsgrouphash)[i];
TAILQ_FOREACH_SAFE(usrp, &hp->lughead, lug_numhash, nusrp) {
TAILQ_REMOVE(&hp->lughead, usrp, lug_numhash);
hp2 = NFSGROUPNAMEHASH(usrp->lug_name,
@ -4223,16 +4256,16 @@ nfsrv_cleanusergroup(void)
crfree(usrp->lug_cred);
free(usrp, M_NFSUSERGROUP);
}
mtx_destroy(&nfsuserhash[i].mtx);
mtx_destroy(&nfsusernamehash[i].mtx);
mtx_destroy(&nfsgroupnamehash[i].mtx);
mtx_destroy(&nfsgrouphash[i].mtx);
mtx_destroy(&NFSD_VNET(nfsuserhash)[i].mtx);
mtx_destroy(&NFSD_VNET(nfsusernamehash)[i].mtx);
mtx_destroy(&NFSD_VNET(nfsgroupnamehash)[i].mtx);
mtx_destroy(&NFSD_VNET(nfsgrouphash)[i].mtx);
}
free(nfsuserhash, M_NFSUSERGROUP);
free(nfsusernamehash, M_NFSUSERGROUP);
free(nfsgrouphash, M_NFSUSERGROUP);
free(nfsgroupnamehash, M_NFSUSERGROUP);
free(nfsrv_dnsname, M_NFSSTRING);
free(NFSD_VNET(nfsuserhash), M_NFSUSERGROUP);
free(NFSD_VNET(nfsusernamehash), M_NFSUSERGROUP);
free(NFSD_VNET(nfsgrouphash), M_NFSUSERGROUP);
free(NFSD_VNET(nfsgroupnamehash), M_NFSUSERGROUP);
free(NFSD_VNET(nfsrv_dnsname), M_NFSSTRING);
}
/*