summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2009-05-09 18:09:17 +0000
committerkan <kan@FreeBSD.org>2009-05-09 18:09:17 +0000
commit7b57a857b7ba934dd819c18d33738253d01f87c5 (patch)
treee0a6bea48a27765461073d412daf8d760867e537
parent11700d839b55c1904f111a054c18b3ba53a9a98c (diff)
downloadFreeBSD-src-7b57a857b7ba934dd819c18d33738253d01f87c5.zip
FreeBSD-src-7b57a857b7ba934dd819c18d33738253d01f87c5.tar.gz
Do not embed struct ucred into larger netcred parent structures.
Credential might need to hang around longer than its parent and be used outside of mnt_explock scope controlling netcred lifetime. Use separate reference-counted ucred allocated separately instead. While there, extend mnt_explock coverage in vfs_stdexpcheck and clean-up some unused declarations in new NFS code. Reported by: John Hickey PR: kern/133439 Reviewed by: dfr, kib
-rw-r--r--sys/fs/nfs/nfsport.h10
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c14
-rw-r--r--sys/fs/nfsserver/nfs_nfsdsocket.c2
-rw-r--r--sys/kern/vfs_export.c44
-rw-r--r--sys/nfsserver/nfs_srvsubs.c3
-rw-r--r--sys/nlm/nlm_prot_impl.c5
-rw-r--r--sys/ufs/ufs/ufs_extern.h1
7 files changed, 37 insertions, 42 deletions
diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h
index e4b3d0a..c1c93a5 100644
--- a/sys/fs/nfs/nfsport.h
+++ b/sys/fs/nfs/nfsport.h
@@ -446,16 +446,6 @@ int nfsmsleep(void *, void *, int, const char *, struct timespec *);
#define VT_NFSV4ROOT "nfsv4root"
/*
- * XXX - not in any system .h file, just vfs_export.c
- * Network address lookup element
- */
-struct netcred {
- struct radix_node netc_rnodes[2];
- int netc_exflags;
- struct ucred netc_anon;
-};
-
-/*
* Define whatever it takes to do a vn_rdwr().
*/
#define NFSD_RDWR(r, v, b, l, o, s, i, c, a, p) \
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 6d39173..09a1d73 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -2565,6 +2565,8 @@ nfsd_fhtovp(struct nfsrv_descript *nd, struct nfsrvfh *nfp,
if (nd->nd_repstat)
vput(*vpp);
}
+ if (credanon != NULL)
+ crfree(credanon);
if (nd->nd_repstat) {
if (startwrite)
vn_finished_write(mp);
@@ -2598,16 +2600,6 @@ fp_getfvp(struct thread *p, int fd, struct file **fpp, struct vnode **vpp)
}
/*
- * Network export information
- */
-struct netexport {
- struct netcred ne_defexported; /* Default export */
- struct radix_node_head *ne_rtable[AF_MAX+1]; /* Individual exports */
-};
-
-struct netexport nfsv4root_export;
-
-/*
* Called from newnfssvc() to update the exports list. Just call
* vfs_export(). This has to be done, since the v4 root fake fs isn't
* in the mount list.
@@ -2861,6 +2853,8 @@ nfsvno_v4rootexport(struct nfsrv_descript *nd)
return (NFSERR_PROGUNAVAIL);
if ((exflags & MNT_EXGSSONLY))
nd->nd_flag |= ND_EXGSSONLY;
+ if (credanon != NULL)
+ crfree(credanon);
return (0);
}
diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c b/sys/fs/nfsserver/nfs_nfsdsocket.c
index 29592a9..a9c7e80 100644
--- a/sys/fs/nfsserver/nfs_nfsdsocket.c
+++ b/sys/fs/nfsserver/nfs_nfsdsocket.c
@@ -870,6 +870,8 @@ nfsrvd_compound(struct nfsrv_descript *nd, int isdgram,
if (!nd->nd_repstat)
nd->nd_repstat = nfsd_excred(nd,
&nes, credanon);
+ if (credanon != NULL)
+ crfree(credanon);
if (!nd->nd_repstat) {
if (vpnes.nes_vfslocked)
nfsvno_unlockvfs(mp);
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 486f4ce6..8e34646 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -68,7 +68,7 @@ static struct netcred *vfs_export_lookup(struct mount *, struct sockaddr *);
struct netcred {
struct radix_node netc_rnodes[2];
int netc_exflags;
- struct ucred netc_anon;
+ struct ucred *netc_anon;
int netc_numsecflavors;
int netc_secflavors[MAXSECFLAVORS];
};
@@ -83,7 +83,7 @@ struct netexport {
/*
* Build hash lists of net addresses and hang them off the mount point.
- * Called by ufs_mount() to set up the lists of export addresses.
+ * Called by vfs_export() to set up the lists of export addresses.
*/
static int
vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
@@ -118,15 +118,14 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
}
np = &nep->ne_defexported;
np->netc_exflags = argp->ex_flags;
- bzero(&np->netc_anon, sizeof(np->netc_anon));
- np->netc_anon.cr_uid = argp->ex_anon.cr_uid;
- np->netc_anon.cr_ngroups = argp->ex_anon.cr_ngroups;
- bcopy(argp->ex_anon.cr_groups, np->netc_anon.cr_groups,
- sizeof(np->netc_anon.cr_groups));
+ np->netc_anon = crget();
+ np->netc_anon->cr_uid = argp->ex_anon.cr_uid;
+ np->netc_anon->cr_ngroups = argp->ex_anon.cr_ngroups;
+ bcopy(argp->ex_anon.cr_groups, np->netc_anon->cr_groups,
+ sizeof(np->netc_anon->cr_groups));
np->netc_numsecflavors = argp->ex_numsecflavors;
bcopy(argp->ex_secflavors, np->netc_secflavors,
sizeof(np->netc_secflavors));
- refcount_init(&np->netc_anon.cr_ref, 1);
MNT_ILOCK(mp);
mp->mnt_flag |= MNT_DEFEXPORTED;
MNT_IUNLOCK(mp);
@@ -204,15 +203,14 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
goto out;
}
np->netc_exflags = argp->ex_flags;
- bzero(&np->netc_anon, sizeof(np->netc_anon));
- np->netc_anon.cr_uid = argp->ex_anon.cr_uid;
- np->netc_anon.cr_ngroups = argp->ex_anon.cr_ngroups;
- bcopy(argp->ex_anon.cr_groups, np->netc_anon.cr_groups,
- sizeof(np->netc_anon.cr_groups));
+ np->netc_anon = crget();
+ np->netc_anon->cr_uid = argp->ex_anon.cr_uid;
+ np->netc_anon->cr_ngroups = argp->ex_anon.cr_ngroups;
+ bcopy(argp->ex_anon.cr_groups, np->netc_anon->cr_groups,
+ sizeof(np->netc_anon->cr_groups));
np->netc_numsecflavors = argp->ex_numsecflavors;
bcopy(argp->ex_secflavors, np->netc_secflavors,
sizeof(np->netc_secflavors));
- refcount_init(&np->netc_anon.cr_ref, 1);
return (0);
out:
free(np, M_NETADDR);
@@ -267,9 +265,9 @@ vfs_export(struct mount *mp, struct export_args *argp)
|| argp->ex_numsecflavors >= MAXSECFLAVORS)
return (EINVAL);
- nep = mp->mnt_export;
error = 0;
lockmgr(&mp->mnt_explock, LK_EXCLUSIVE, NULL);
+ nep = mp->mnt_export;
if (argp->ex_flags & MNT_DELEXPORT) {
if (nep == NULL) {
error = ENOENT;
@@ -375,8 +373,9 @@ vfs_setpublicfs(struct mount *mp, struct netexport *nep,
* If an indexfile was specified, pull it in.
*/
if (argp->ex_indexfile != NULL) {
- nfs_pub.np_index = malloc(MAXNAMLEN + 1, M_TEMP,
- M_WAITOK);
+ if (nfs_pub.np_index != NULL)
+ nfs_pub.np_index = malloc(MAXNAMLEN + 1, M_TEMP,
+ M_WAITOK);
error = copyinstr(argp->ex_indexfile, nfs_pub.np_index,
MAXNAMLEN, (size_t *)0);
if (!error) {
@@ -392,6 +391,7 @@ vfs_setpublicfs(struct mount *mp, struct netexport *nep,
}
if (error) {
free(nfs_pub.np_index, M_TEMP);
+ nfs_pub.np_index = NULL;
return (error);
}
}
@@ -461,15 +461,19 @@ vfs_stdcheckexp(struct mount *mp, struct sockaddr *nam, int *extflagsp,
lockmgr(&mp->mnt_explock, LK_SHARED, NULL);
np = vfs_export_lookup(mp, nam);
- lockmgr(&mp->mnt_explock, LK_RELEASE, NULL);
- if (np == NULL)
+ if (np == NULL) {
+ lockmgr(&mp->mnt_explock, LK_RELEASE, NULL);
+ *credanonp = NULL;
return (EACCES);
+ }
*extflagsp = np->netc_exflags;
- *credanonp = &np->netc_anon;
+ if ((*credanonp = np->netc_anon) != NULL)
+ crhold(*credanonp);
if (numsecflavors)
*numsecflavors = np->netc_numsecflavors;
if (secflavors)
*secflavors = np->netc_secflavors;
+ lockmgr(&mp->mnt_explock, LK_RELEASE, NULL);
return (0);
}
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index d154463..3f54664 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -1193,6 +1193,9 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, int *vfslockedp,
if (!lockflag)
VOP_UNLOCK(*vpp, 0);
out:
+ if (credanon != NULL)
+ crfree(credanon);
+
if (error) {
VFS_UNLOCK_GIANT(vfslocked);
} else
diff --git a/sys/nlm/nlm_prot_impl.c b/sys/nlm/nlm_prot_impl.c
index 1ddaf3e..a46d432 100644
--- a/sys/nlm/nlm_prot_impl.c
+++ b/sys/nlm/nlm_prot_impl.c
@@ -1752,7 +1752,8 @@ nlm_get_vfs_state(struct nlm_host *host, struct svc_req *rqstp,
}
if (cred->cr_uid == 0 || (exflags & MNT_EXPORTANON)) {
crfree(cred);
- cred = crhold(credanon);
+ cred = credanon;
+ credanon = NULL;
}
/*
@@ -1772,6 +1773,8 @@ nlm_get_vfs_state(struct nlm_host *host, struct svc_req *rqstp,
out:
if (cred)
crfree(cred);
+ if (credanon)
+ crfree(credanon);
return (error);
}
diff --git a/sys/ufs/ufs/ufs_extern.h b/sys/ufs/ufs/ufs_extern.h
index 2cb9801..b2e4a97 100644
--- a/sys/ufs/ufs/ufs_extern.h
+++ b/sys/ufs/ufs/ufs_extern.h
@@ -38,7 +38,6 @@ struct direct;
struct indir;
struct inode;
struct mount;
-struct netcred;
struct thread;
struct sockaddr;
struct ucred;
OpenPOWER on IntegriCloud