diff options
author | Al Viro <viro@ftp.linux.org.uk> | 2006-10-20 02:28:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-20 13:26:39 -0400 |
commit | cc45f0175088e000ac7493e5e3f05579b6f7d240 (patch) | |
tree | cc53e59824097b45a39ca332b3451aedc43d4fe2 /fs/nfsd | |
parent | b7766da7f7395b74dec9e52005b7dac0d09391a4 (diff) |
[PATCH] bug: nfsd/nfs4xdr.c misuse of ERR_PTR()
a) ERR_PTR(nfserr_something) is a bad idea;
IS_ERR() will be false for it.
b) mixing nfserr_.... with -EOPNOTSUPP is
even worse idea.
nfsd4_path() does both; caller expects to get NFS protocol error out it if
anything goes wrong, but if it does we either do not notice (see (a)) or get
host-endian negative (see (b)).
IOW, that's a case when we can't use ERR_PTR() to return error, even though we
return a pointer in case of success.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Trond Myklebust <trond.myklebust@fys.uio.no>
Acked-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 21 |
1 files changed, 11 insertions, 10 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 41fc241b729a..77be0c4785e6 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -1292,16 +1292,15 @@ static int nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, | |||
1292 | * Returned string is safe to use as long as the caller holds a reference | 1292 | * Returned string is safe to use as long as the caller holds a reference |
1293 | * to @exp. | 1293 | * to @exp. |
1294 | */ | 1294 | */ |
1295 | static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp) | 1295 | static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, u32 *stat) |
1296 | { | 1296 | { |
1297 | struct svc_fh tmp_fh; | 1297 | struct svc_fh tmp_fh; |
1298 | char *path, *rootpath; | 1298 | char *path, *rootpath; |
1299 | int stat; | ||
1300 | 1299 | ||
1301 | fh_init(&tmp_fh, NFS4_FHSIZE); | 1300 | fh_init(&tmp_fh, NFS4_FHSIZE); |
1302 | stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle); | 1301 | *stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle); |
1303 | if (stat) | 1302 | if (*stat) |
1304 | return ERR_PTR(stat); | 1303 | return NULL; |
1305 | rootpath = tmp_fh.fh_export->ex_path; | 1304 | rootpath = tmp_fh.fh_export->ex_path; |
1306 | 1305 | ||
1307 | path = exp->ex_path; | 1306 | path = exp->ex_path; |
@@ -1309,7 +1308,8 @@ static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp) | |||
1309 | if (strncmp(path, rootpath, strlen(rootpath))) { | 1308 | if (strncmp(path, rootpath, strlen(rootpath))) { |
1310 | printk("nfsd: fs_locations failed;" | 1309 | printk("nfsd: fs_locations failed;" |
1311 | "%s is not contained in %s\n", path, rootpath); | 1310 | "%s is not contained in %s\n", path, rootpath); |
1312 | return ERR_PTR(-EOPNOTSUPP); | 1311 | *stat = nfserr_notsupp; |
1312 | return NULL; | ||
1313 | } | 1313 | } |
1314 | 1314 | ||
1315 | return path + strlen(rootpath); | 1315 | return path + strlen(rootpath); |
@@ -1322,13 +1322,14 @@ static int nfsd4_encode_fs_locations(struct svc_rqst *rqstp, | |||
1322 | struct svc_export *exp, | 1322 | struct svc_export *exp, |
1323 | u32 **pp, int *buflen) | 1323 | u32 **pp, int *buflen) |
1324 | { | 1324 | { |
1325 | int status, i; | 1325 | u32 status; |
1326 | int i; | ||
1326 | u32 *p = *pp; | 1327 | u32 *p = *pp; |
1327 | struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; | 1328 | struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; |
1328 | char *root = nfsd4_path(rqstp, exp); | 1329 | char *root = nfsd4_path(rqstp, exp, &status); |
1329 | 1330 | ||
1330 | if (IS_ERR(root)) | 1331 | if (status) |
1331 | return PTR_ERR(root); | 1332 | return status; |
1332 | status = nfsd4_encode_components('/', root, &p, buflen); | 1333 | status = nfsd4_encode_components('/', root, &p, buflen); |
1333 | if (status) | 1334 | if (status) |
1334 | return status; | 1335 | return status; |