diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-09-02 16:48:32 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2009-09-03 16:57:57 -0400 |
commit | 2671a4bf3516757ca028c139a7902a50f2bd994a (patch) | |
tree | 9b60719bdd52cdae10f4b64525c13f072e1ac7b0 | |
parent | bc6c53d5a1383d5d9632adf33bd03458cfc0869d (diff) |
NFSd: Fix filehandle leak in exp_pseudoroot() and nfsd4_path()
nfsd4_path() allocates a temporary filehandle and then fails to free it
before the function exits, leaking reference counts to the dentry and
export that it refers to.
Also, nfsd4_lookupp() puts the result of exp_pseudoroot() in a temporary
filehandle which it releases on success of exp_pseudoroot() but not on
failure; fix exp_pseudoroot to ensure that on failure it releases the
filehandle before returning.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r-- | fs/nfsd/export.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 15 |
2 files changed, 12 insertions, 5 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index d9462643155c..984a5ebcc1d6 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -1341,6 +1341,8 @@ exp_pseudoroot(struct svc_rqst *rqstp, struct svc_fh *fhp) | |||
1341 | if (rv) | 1341 | if (rv) |
1342 | goto out; | 1342 | goto out; |
1343 | rv = check_nfsd_access(exp, rqstp); | 1343 | rv = check_nfsd_access(exp, rqstp); |
1344 | if (rv) | ||
1345 | fh_put(fhp); | ||
1344 | out: | 1346 | out: |
1345 | exp_put(exp); | 1347 | exp_put(exp); |
1346 | return rv; | 1348 | return rv; |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 00ed16a18497..0fbd50cee1f6 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -1599,7 +1599,8 @@ static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, | |||
1599 | static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat) | 1599 | static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat) |
1600 | { | 1600 | { |
1601 | struct svc_fh tmp_fh; | 1601 | struct svc_fh tmp_fh; |
1602 | char *path, *rootpath; | 1602 | char *path = NULL, *rootpath; |
1603 | size_t rootlen; | ||
1603 | 1604 | ||
1604 | fh_init(&tmp_fh, NFS4_FHSIZE); | 1605 | fh_init(&tmp_fh, NFS4_FHSIZE); |
1605 | *stat = exp_pseudoroot(rqstp, &tmp_fh); | 1606 | *stat = exp_pseudoroot(rqstp, &tmp_fh); |
@@ -1609,14 +1610,18 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 * | |||
1609 | 1610 | ||
1610 | path = exp->ex_pathname; | 1611 | path = exp->ex_pathname; |
1611 | 1612 | ||
1612 | if (strncmp(path, rootpath, strlen(rootpath))) { | 1613 | rootlen = strlen(rootpath); |
1614 | if (strncmp(path, rootpath, rootlen)) { | ||
1613 | dprintk("nfsd: fs_locations failed;" | 1615 | dprintk("nfsd: fs_locations failed;" |
1614 | "%s is not contained in %s\n", path, rootpath); | 1616 | "%s is not contained in %s\n", path, rootpath); |
1615 | *stat = nfserr_notsupp; | 1617 | *stat = nfserr_notsupp; |
1616 | return NULL; | 1618 | path = NULL; |
1619 | goto out; | ||
1617 | } | 1620 | } |
1618 | 1621 | path += rootlen; | |
1619 | return path + strlen(rootpath); | 1622 | out: |
1623 | fh_put(&tmp_fh); | ||
1624 | return path; | ||
1620 | } | 1625 | } |
1621 | 1626 | ||
1622 | /* | 1627 | /* |