summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorrmacklem <rmacklem@FreeBSD.org>2009-06-08 18:41:23 +0000
committerrmacklem <rmacklem@FreeBSD.org>2009-06-08 18:41:23 +0000
commit367af0776014707efce6c57518a53ec63dbaed1b (patch)
tree72a755af7b98815a53cf872352070130619770f1 /sys/fs
parentca6dbec08b990a59e5485d094466fd82165a5c41 (diff)
downloadFreeBSD-src-367af0776014707efce6c57518a53ec63dbaed1b.zip
FreeBSD-src-367af0776014707efce6c57518a53ec63dbaed1b.tar.gz
Fix nfscl_getcl() so that it doesn't crash when it is called to
do an NFSv4 Close operation with the cred argument NULL. Also, clarify what NULL arguments mean in the function's comment. Approved by: kib (mentor)
Diffstat (limited to 'sys/fs')
-rw-r--r--sys/fs/nfsclient/nfs_clstate.c49
1 files changed, 29 insertions, 20 deletions
diff --git a/sys/fs/nfsclient/nfs_clstate.c b/sys/fs/nfsclient/nfs_clstate.c
index 2295627..8cc2ce2 100644
--- a/sys/fs/nfsclient/nfs_clstate.c
+++ b/sys/fs/nfsclient/nfs_clstate.c
@@ -663,8 +663,9 @@ nfscl_openrelease(struct nfsclopen *op, int error, int candelete)
* client data structures to do the SetClientId/SetClientId_confirm,
* but will release that lock and return the clientid with a refernce
* count on it.
- * If the p argument is NULL, it will not do the SetClientId/Confirm
- * and the cred argument is not used, so it can be NULL too.
+ * If the "cred" argument is NULL, a new clientid should not be created.
+ * If the "p" argument is NULL, a SetClientID/SetClientIDConfirm cannot
+ * be done.
* It always clpp with a reference count on it, unless returning an error.
*/
APPLESTATIC int
@@ -672,28 +673,35 @@ nfscl_getcl(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
struct nfsclclient **clpp)
{
struct nfsclclient *clp;
- struct nfsclclient *newclp;
+ struct nfsclclient *newclp = NULL;
struct nfscllockowner *lp, *nlp;
struct nfsmount *nmp = VFSTONFS(vnode_mount(vp));
struct prison *pr;
char uuid[HOSTUUIDLEN];
int igotlock = 0, error, trystalecnt, clidinusedelay, i;
- u_int16_t idlen;
-
- pr = cred->cr_prison;
- mtx_lock(&pr->pr_mtx);
- strlcpy(uuid, pr->pr_uuid, sizeof uuid);
- mtx_unlock(&pr->pr_mtx);
- idlen = strlen(uuid);
- if (idlen > 0)
- idlen += sizeof (u_int64_t);
- else
- idlen += sizeof (u_int64_t) + 16; /* 16 random bytes */
- MALLOC(newclp, struct nfsclclient *, sizeof (struct nfsclclient) +
- idlen - 1, M_NFSCLCLIENT, M_WAITOK);
+ u_int16_t idlen = 0;
+
+ if (cred != NULL) {
+ pr = cred->cr_prison;
+ mtx_lock(&pr->pr_mtx);
+ strlcpy(uuid, pr->pr_uuid, sizeof uuid);
+ mtx_unlock(&pr->pr_mtx);
+ idlen = strlen(uuid);
+ if (idlen > 0)
+ idlen += sizeof (u_int64_t);
+ else
+ idlen += sizeof (u_int64_t) + 16; /* 16 random bytes */
+ MALLOC(newclp, struct nfsclclient *,
+ sizeof (struct nfsclclient) + idlen - 1, M_NFSCLCLIENT,
+ M_WAITOK);
+ }
NFSLOCKCLSTATE();
clp = nmp->nm_clp;
if (clp == NULL) {
+ if (newclp == NULL) {
+ NFSUNLOCKCLSTATE();
+ return (EACCES);
+ }
clp = newclp;
NFSBZERO((caddr_t)clp, sizeof(struct nfsclclient) + idlen - 1);
clp->nfsc_idlen = idlen;
@@ -714,7 +722,8 @@ nfscl_getcl(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
nfscl_start_renewthread(clp);
} else {
NFSUNLOCKCLSTATE();
- FREE((caddr_t)newclp, M_NFSCLCLIENT);
+ if (newclp != NULL)
+ FREE((caddr_t)newclp, M_NFSCLCLIENT);
}
NFSLOCKCLSTATE();
while ((clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID) == 0 && !igotlock)
@@ -730,7 +739,7 @@ nfscl_getcl(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
if ((clp->nfsc_flags & NFSCLFLAGS_HASCLIENTID) == 0) {
if (!igotlock)
panic("nfscl_clget");
- if (p == NULL) {
+ if (p == NULL || cred == NULL) {
NFSLOCKCLSTATE();
nfsv4_unlock(&clp->nfsc_lock, 0);
NFSUNLOCKCLSTATE();
@@ -762,8 +771,8 @@ nfscl_getcl(vnode_t vp, struct ucred *cred, NFSPROC_T *p,
clidinusedelay = 120;
trystalecnt = 3;
do {
- error = nfsrpc_setclient(VFSTONFS(vnode_mount(vp)), clp,
- cred, p);
+ error = nfsrpc_setclient(VFSTONFS(vnode_mount(vp)),
+ clp, cred, p);
if (error == NFSERR_STALECLIENTID ||
error == NFSERR_STALEDONTRECOVER ||
error == NFSERR_CLIDINUSE) {
OpenPOWER on IntegriCloud