- fix some leaks in nfsd, introduced by kauth changes.

- simplify code.
- add some assertions.
- wrap some long lines.
- remove an unnecessary ";".
This commit is contained in:
yamt 2006-05-18 12:44:45 +00:00
parent b5420599d2
commit b861e24c71
6 changed files with 112 additions and 108 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_export.c,v 1.12 2006/05/18 10:07:34 yamt Exp $ */
/* $NetBSD: nfs_export.c,v 1.13 2006/05/18 12:44:45 yamt Exp $ */
/*-
* Copyright (c) 1997, 1998, 2004, 2005 The NetBSD Foundation, Inc.
@ -82,7 +82,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nfs_export.c,v 1.12 2006/05/18 10:07:34 yamt Exp $");
__KERNEL_RCSID(0, "$NetBSD: nfs_export.c,v 1.13 2006/05/18 12:44:45 yamt Exp $");
#include "opt_compat_netbsd.h"
#include "opt_inet.h"
@ -501,9 +501,9 @@ hang_addrlist(struct mount *mp, struct netexport *nep,
if (mp->mnt_flag & MNT_DEFEXPORTED)
return EPERM;
np = &nep->ne_defexported;
KASSERT(np->netc_anon == NULL);
np->netc_anon = kauth_cred_alloc();
np->netc_exflags = argp->ex_flags;
if (np->netc_anon == NULL) /* XXX elad */
np->netc_anon = kauth_cred_alloc();
kauth_cred_uucvt(np->netc_anon, &argp->ex_anon);
mp->mnt_flag |= MNT_DEFEXPORTED;
return 0;
@ -514,6 +514,7 @@ hang_addrlist(struct mount *mp, struct netexport *nep,
i = sizeof(struct netcred) + argp->ex_addrlen + argp->ex_masklen;
np = malloc(i, M_NETADDR, M_WAITOK | M_ZERO);
np->netc_anon = kauth_cred_alloc();
saddr = (struct sockaddr *)(np + 1);
error = copyin(argp->ex_addr, saddr, argp->ex_addrlen);
if (error)
@ -571,8 +572,6 @@ hang_addrlist(struct mount *mp, struct netexport *nep,
enp->netc_refcnt = 1;
np->netc_exflags = argp->ex_flags;
if (np->netc_anon == NULL) /* XXX elad */
np->netc_anon = kauth_cred_alloc();
kauth_cred_uucvt(np->netc_anon, &argp->ex_anon);
return 0;
check:
@ -582,6 +581,8 @@ check:
else
error = 0;
out:
KASSERT(np->netc_anon != NULL);
kauth_cred_free(np->netc_anon);
free(np, M_NETADDR);
return error;
}
@ -638,8 +639,11 @@ free_netcred(struct radix_node *rn, void *w)
struct netcred *np = (struct netcred *)(void *)rn;
(*rnh->rnh_deladdr)(rn->rn_key, rn->rn_mask, rnh);
if (--(np->netc_refcnt) <= 0)
if (--(np->netc_refcnt) <= 0) {
KASSERT(np->netc_anon != NULL);
kauth_cred_free(np->netc_anon);
free(np, M_NETADDR);
}
return 0;
}
@ -666,6 +670,16 @@ netexport_clear(struct netexport *ne)
}
}
if ((mp->mnt_flag & MNT_DEFEXPORTED) != 0) {
struct netcred *np = &ne->ne_defexported;
KASSERT(np->netc_anon != NULL);
kauth_cred_free(np->netc_anon);
np->netc_anon = NULL;
} else {
KASSERT(ne->ne_defexported.netc_anon == NULL);
}
mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_nqlease.c,v 1.62 2006/05/14 21:32:21 elad Exp $ */
/* $NetBSD: nfs_nqlease.c,v 1.63 2006/05/18 12:44:45 yamt Exp $ */
/*
* Copyright (c) 1992, 1993
@ -49,7 +49,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nfs_nqlease.c,v 1.62 2006/05/14 21:32:21 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: nfs_nqlease.c,v 1.63 2006/05/18 12:44:45 yamt Exp $");
#include "fs_nfs.h"
#include "opt_nfs.h"
@ -942,12 +942,9 @@ nfsmout:
/*
* Called for client side callbacks
*/
int
nqnfs_callback(nmp, mrep, md, dpos, l)
struct nfsmount *nmp;
struct mbuf *mrep, *md;
caddr_t dpos;
struct lwp *l;
static int
nqnfs_callback1(struct nfsmount *nmp, struct mbuf *mrep, struct mbuf *md,
caddr_t dpos, struct lwp *l, struct nfsrv_descript *nfsd)
{
struct vnode *vp;
u_int32_t *tl;
@ -957,8 +954,6 @@ nqnfs_callback(nmp, mrep, md, dpos, l)
struct nfsnode *np;
struct nfsd tnfsd;
struct nfssvc_sock *slp;
struct nfsrv_descript ndesc;
struct nfsrv_descript *nfsd = &ndesc;
struct mbuf **mrq = (struct mbuf **)0, *mb, *mreq;
int error = 0, cache = 0;
char *cp2, *bpos;
@ -995,8 +990,23 @@ nqnfs_callback(nmp, mrep, md, dpos, l)
}
}
vput(vp);
kauth_cred_free(nfsd->nd_cr);
nfsm_srvdone;
}
int
nqnfs_callback(struct nfsmount *nmp, struct mbuf *mrep, struct mbuf *md,
caddr_t dpos, struct lwp *l)
{
struct nfsrv_descript *nd;
int error;
nd = nfsdreq_alloc();
error = nqnfs_callback1(nmp, mrep, md, dpos, l, nd);
nfsdreq_free(nd);
return error;
}
#endif /* NFS && !NFS_V2_ONLY */
#ifdef NFS /* Needed in V2_ONLY case for Kerberos stuff */

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_socket.c,v 1.130 2006/05/14 21:32:21 elad Exp $ */
/* $NetBSD: nfs_socket.c,v 1.131 2006/05/18 12:44:45 yamt Exp $ */
/*
* Copyright (c) 1989, 1991, 1993, 1995
@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nfs_socket.c,v 1.130 2006/05/14 21:32:21 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: nfs_socket.c,v 1.131 2006/05/18 12:44:45 yamt Exp $");
#include "fs_nfs.h"
#include "opt_nfs.h"
@ -1517,9 +1517,11 @@ nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
memset(&ktvout, 0, sizeof ktvout); /* XXX gcc */
LIST_FOREACH(nuidp, NUIDHASH(slp, kauth_cred_geteuid(nd->nd_cr)),
LIST_FOREACH(nuidp,
NUIDHASH(slp, kauth_cred_geteuid(nd->nd_cr)),
nu_hash) {
if (kauth_cred_geteuid(nuidp->nu_cr) == kauth_cred_geteuid(nd->nd_cr) &&
if (kauth_cred_geteuid(nuidp->nu_cr) ==
kauth_cred_geteuid(nd->nd_cr) &&
(!nd->nd_nam2 || netaddr_match(
NU_NETFAM(nuidp), &nuidp->nu_haddr,
nd->nd_nam2)))
@ -1545,7 +1547,8 @@ nfs_rephead(siz, nd, slp, err, cache, frev, mrq, mbp, bposp)
*tl = ktvout.tv_sec;
nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
*tl++ = ktvout.tv_usec;
*tl++ = txdr_unsigned(kauth_cred_geteuid(nuidp->nu_cr));
*tl++ = txdr_unsigned(
kauth_cred_geteuid(nuidp->nu_cr));
} else {
*tl++ = 0;
*tl++ = 0;
@ -1924,7 +1927,7 @@ nfs_rcvunlock(nmp)
/*
* Parse an RPC request
* - verify it
* - fill in the cred struct.
* - allocate and fill in the cred.
*/
int
nfs_getreq(nd, nfsd, has_header)
@ -1947,6 +1950,7 @@ nfs_getreq(nd, nfsd, has_header)
memset(&tvout, 0, sizeof tvout); /* XXX gcc */
KASSERT(nd->nd_cr == NULL);
mrep = nd->nd_mrep;
md = nd->nd_md;
dpos = nd->nd_dpos;
@ -2014,16 +2018,16 @@ nfs_getreq(nd, nfsd, has_header)
uid_t uid;
gid_t gid, *grbuf;
nd->nd_cr = kauth_cred_alloc();
len = fxdr_unsigned(int, *++tl);
if (len < 0 || len > NFS_MAXNAMLEN) {
m_freem(mrep);
return (EBADRPC);
error = EBADRPC;
goto errout;
}
nfsm_adv(nfsm_rndup(len));
nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
nd->nd_cr = kauth_cred_alloc();
uid = fxdr_unsigned(uid_t, *tl++);
gid = fxdr_unsigned(gid_t, *tl++);
kauth_cred_setuid(nd->nd_cr, uid);
@ -2035,10 +2039,9 @@ nfs_getreq(nd, nfsd, has_header)
len = fxdr_unsigned(int, *tl);
if (len < 0 || len > RPCAUTH_UNIXGIDS) {
kauth_cred_free(nd->nd_cr);
nd->nd_cr = NULL;
m_freem(mrep);
return (EBADRPC);
error = EBADRPC;
goto errout;
}
nfsm_dissect(tl, u_int32_t *, (len + 2) * NFSX_UNSIGNED);
@ -2054,10 +2057,9 @@ nfs_getreq(nd, nfsd, has_header)
len = fxdr_unsigned(int, *++tl);
if (len < 0 || len > RPCAUTH_MAXSIZ) {
kauth_cred_free(nd->nd_cr);
kauth_cred_free(nd->nd_cr);
m_freem(mrep);
return (EBADRPC);
error = EBADRPC;
goto errout;
}
if (len > 0)
nfsm_adv(nfsm_rndup(len));
@ -2070,7 +2072,8 @@ nfs_getreq(nd, nfsd, has_header)
nfsd->nfsd_authlen = uio.uio_resid + NFSX_UNSIGNED;
if (uio.uio_resid > (len - 2 * NFSX_UNSIGNED)) {
m_freem(mrep);
return (EBADRPC);
error = EBADRPC;
goto errout;
}
uio.uio_offset = 0;
uio.uio_iov = &iov;
@ -2156,9 +2159,10 @@ nfs_getreq(nd, nfsd, has_header)
nd->nd_procnum = NFSPROC_NOOP;
return (0);
}
nfsrv_setcred(nuidp->nu_cr, &nd->nd_cr);
kauth_cred_hold(nuidp->nu_cr);
nd->nd_cr = nuidp->nu_cr;
nd->nd_flag |= ND_KERBNICK;
};
}
} else {
nd->nd_repstat = (NFSERR_AUTHERR | AUTH_REJECTCRED);
nd->nd_procnum = NFSPROC_NOOP;
@ -2180,8 +2184,16 @@ nfs_getreq(nd, nfsd, has_header)
nd->nd_duration = NQ_MINLEASE;
nd->nd_md = md;
nd->nd_dpos = dpos;
KASSERT((nd->nd_cr == NULL && (nfsd->nfsd_flag & NFSD_NEEDAUTH) != 0)
|| (nd->nd_cr != NULL && (nfsd->nfsd_flag & NFSD_NEEDAUTH) == 0));
return (0);
nfsmout:
errout:
KASSERT(error != 0);
if (nd->nd_cr != NULL) {
kauth_cred_free(nd->nd_cr);
nd->nd_cr = NULL;
}
return (error);
}
@ -2547,14 +2559,14 @@ nfsrv_dorec(slp, nfsd, ndp)
nam->m_next = NULL;
} else
nam = NULL;
nd = pool_get(&nfs_srvdesc_pool, PR_WAITOK);
nd = nfsdreq_alloc();
nd->nd_md = nd->nd_mrep = m;
nd->nd_nam2 = nam;
nd->nd_dpos = mtod(m, caddr_t);
error = nfs_getreq(nd, nfsd, TRUE);
if (error) {
m_freem(nam);
pool_put(&nfs_srvdesc_pool, nd);
nfsdreq_free(nd);
return (error);
}
*ndp = nd;
@ -2562,6 +2574,28 @@ nfsrv_dorec(slp, nfsd, ndp)
return (0);
}
struct nfsrv_descript *
nfsdreq_alloc(void)
{
struct nfsrv_descript *nd;
nd = pool_get(&nfs_srvdesc_pool, PR_WAITOK);
nd->nd_cr = NULL;
return nd;
}
void
nfsdreq_free(struct nfsrv_descript *nd)
{
kauth_cred_t cr;
cr = nd->nd_cr;
if (cr != NULL) {
KASSERT(kauth_cred_getrefcnt(cr) == 1);
kauth_cred_free(cr);
}
pool_put(&nfs_srvdesc_pool, nd);
}
/*
* Search for a sleeping nfsd and wake it up.
@ -2624,7 +2658,7 @@ again:
if (nd->nd_nam2) {
m_free(nd->nd_nam2);
}
pool_put(&nfs_srvdesc_pool, nd);
nfsdreq_free(nd);
simple_lock(&slp->ns_lock);
KASSERT((slp->ns_flag & SLP_SENDING) != 0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_subs.c,v 1.162 2006/05/14 21:32:21 elad Exp $ */
/* $NetBSD: nfs_subs.c,v 1.163 2006/05/18 12:44:45 yamt Exp $ */
/*
* Copyright (c) 1989, 1993
@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.162 2006/05/14 21:32:21 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: nfs_subs.c,v 1.163 2006/05/18 12:44:45 yamt Exp $");
#include "fs_nfs.h"
#include "opt_nfs.h"
@ -2923,52 +2923,6 @@ nfsrv_errmap(nd, err)
return (NFSERR_IO);
}
/*
* Sort the group list in increasing numerical order.
* (Insertion sort by Chris Torek, who was grossed out by the bubble sort
* that used to be here.)
*/
void
nfsrvw_sort(list, num)
gid_t *list;
int num;
{
int i, j;
gid_t v;
/* Insertion sort. */
for (i = 1; i < num; i++) {
v = list[i];
/* find correct slot for value v, moving others up */
for (j = i; --j >= 0 && v < list[j];)
list[j + 1] = list[j];
list[j + 1] = v;
}
}
/*
* copy credentials making sure that the result can be compared with memcmp().
*/
void
nfsrv_setcred(incred, outcred)
kauth_cred_t incred, *outcred;
{
/*
* XXX elad: this is another case where the original code just
* messed with the struct members, more specifically,
* set the reference count. if we have more than one
* reference, it means we have a user of these
* credentials that didn't kauth_cred_hold().
*/
#ifdef DIAGNOSTIC
if (kauth_cred_getrefcnt(*outcred) > 1)
panic("nfsrv_setcred: possible memory leak");
#endif /* DIAGNOSTIC */
*outcred = kauth_cred_copy(*outcred);
kauth_cred_clone(incred, *outcred);
}
u_int32_t
nfs_getxid()
{

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_syscalls.c,v 1.92 2006/05/14 21:32:21 elad Exp $ */
/* $NetBSD: nfs_syscalls.c,v 1.93 2006/05/18 12:44:45 yamt Exp $ */
/*
* Copyright (c) 1989, 1993
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: nfs_syscalls.c,v 1.92 2006/05/14 21:32:21 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: nfs_syscalls.c,v 1.93 2006/05/18 12:44:45 yamt Exp $");
#include "fs_nfs.h"
#include "opt_nfs.h"
@ -298,14 +298,16 @@ sys_nfssvc(l, v, retval)
*/
LIST_FOREACH(nuidp, NUIDHASH(slp, nsd->nsd_cr.cr_uid),
nu_hash) {
if (kauth_cred_geteuid(nuidp->nu_cr) == nsd->nsd_cr.cr_uid &&
if (kauth_cred_geteuid(nuidp->nu_cr) ==
nsd->nsd_cr.cr_uid &&
(!nfsd->nfsd_nd->nd_nam2 ||
netaddr_match(NU_NETFAM(nuidp),
&nuidp->nu_haddr, nfsd->nfsd_nd->nd_nam2)))
break;
}
if (nuidp) {
nfsrv_setcred(nuidp->nu_cr, &nfsd->nfsd_nd->nd_cr);
kauth_cred_hold(nuidp->nu_cr);
nfsd->nfsd_nd->nd_cr = nuidp->nu_cr;
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
} else {
/*
@ -332,10 +334,6 @@ sys_nfssvc(l, v, retval)
}
nuidp->nu_flag = 0;
kauth_cred_uucvt(nuidp->nu_cr, &nsd->nsd_cr);
#if 0 /* XXX elad - kernel auth makes sure this can't happen. */
if (nuidp->nu_cr.cr_ngroups > NGROUPS)
nuidp->nu_cr.cr_ngroups = NGROUPS;
#endif /* XXX elad */
nuidp->nu_timestamp = nsd->nsd_timestamp;
nuidp->nu_expire = time.tv_sec + nsd->nsd_ttl;
/*
@ -367,8 +365,8 @@ sys_nfssvc(l, v, retval)
nu_lru);
LIST_INSERT_HEAD(NUIDHASH(slp, nsd->nsd_uid),
nuidp, nu_hash);
nfsrv_setcred(nuidp->nu_cr,
&nfsd->nfsd_nd->nd_cr);
kauth_cred_hold(nuidp->nu_cr);
nfsd->nfsd_nd->nd_cr = nuidp->nu_cr;
nfsd->nfsd_nd->nd_flag |= ND_KERBFULL;
}
}
@ -628,9 +626,7 @@ nfssvc_nfsd(nsd, argp, l)
}
if (error || (slp->ns_flag & SLP_VALID) == 0) {
if (nd) {
if (nd->nd_cr != NULL)
kauth_cred_destroy(nd->nd_cr);
pool_put(&nfs_srvdesc_pool, nd);
nfsdreq_free(nd);
nd = NULL;
}
nfsd->nfsd_slp = NULL;
@ -818,9 +814,7 @@ nfssvc_nfsd(nsd, argp, l)
break;
}
if (nd) {
if (nd->nd_cr != NULL)
kauth_cred_destroy(nd->nd_cr);
pool_put(&nfs_srvdesc_pool, nd);
nfsdreq_free(nd);
nd = NULL;
}
@ -909,9 +903,7 @@ nfsrv_zapsock(slp)
for (nwp = LIST_FIRST(&slp->ns_tq); nwp; nwp = nnwp) {
nnwp = LIST_NEXT(nwp, nd_tq);
LIST_REMOVE(nwp, nd_tq);
if (nwp->nd_cr != NULL)
kauth_cred_destroy(nwp->nd_cr);
pool_put(&nfs_srvdesc_pool, nwp);
nfsdreq_free(nwp);
}
splx(s);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: nfs_var.h,v 1.59 2006/05/14 21:32:21 elad Exp $ */
/* $NetBSD: nfs_var.h,v 1.60 2006/05/18 12:44:45 yamt Exp $ */
/*-
* Copyright (c) 1996 The NetBSD Foundation, Inc.
@ -232,6 +232,8 @@ int nfsdsock_lock(struct nfssvc_sock *, boolean_t);
void nfsdsock_unlock(struct nfssvc_sock *);
int nfsdsock_drain(struct nfssvc_sock *);
int nfsdsock_sendreply(struct nfssvc_sock *, struct nfsrv_descript *);
void nfsdreq_free(struct nfsrv_descript *);
struct nfsrv_descript *nfsdreq_alloc(void);
/* nfs_srvcache.c */
void nfsrv_initcache(void);
@ -295,8 +297,6 @@ void nfs_add_tobecommitted_range(struct vnode *, off_t, off_t);
void nfs_del_tobecommitted_range(struct vnode *, off_t, off_t);
int nfsrv_errmap(struct nfsrv_descript *, int);
void nfsrvw_sort(gid_t *, int);
void nfsrv_setcred(kauth_cred_t, kauth_cred_t *);
void nfs_cookieheuristic(struct vnode *, int *, struct lwp *, kauth_cred_t);
u_int32_t nfs_getxid(void);