diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2007-11-11 15:43:12 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-02-01 16:42:03 -0500 |
commit | ca2a05aa7c72309ee65164c78fa2be7a5038215e (patch) | |
tree | f362d7c14652dfea0d93508007f8fc87d10d6980 /fs/nfsd | |
parent | a490c681cbcf65d548138c377bb691c85824d323 (diff) |
nfsd: Fix handling of negative lengths in read_buf()
The length "nbytes" passed into read_buf should never be negative, but
we check only for too-large values of "nbytes", not for too-small
values. Make nbytes unsigned, so it's clear that the former tests are
sufficient. (Despite this read_buf() currently correctly returns an xdr
error in the case of a negative length, thanks to an unsigned
comparison with size_of() and bounds-checking in kmalloc(). This seems
very fragile, though.)
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 57333944af7f..bf1e792a65a0 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -148,12 +148,12 @@ xdr_error: \ | |||
148 | } \ | 148 | } \ |
149 | } while (0) | 149 | } while (0) |
150 | 150 | ||
151 | static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) | 151 | static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) |
152 | { | 152 | { |
153 | /* We want more bytes than seem to be available. | 153 | /* We want more bytes than seem to be available. |
154 | * Maybe we need a new page, maybe we have just run out | 154 | * Maybe we need a new page, maybe we have just run out |
155 | */ | 155 | */ |
156 | int avail = (char*)argp->end - (char*)argp->p; | 156 | unsigned int avail = (char *)argp->end - (char *)argp->p; |
157 | __be32 *p; | 157 | __be32 *p; |
158 | if (avail + argp->pagelen < nbytes) | 158 | if (avail + argp->pagelen < nbytes) |
159 | return NULL; | 159 | return NULL; |
@@ -169,6 +169,11 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) | |||
169 | return NULL; | 169 | return NULL; |
170 | 170 | ||
171 | } | 171 | } |
172 | /* | ||
173 | * The following memcpy is safe because read_buf is always | ||
174 | * called with nbytes > avail, and the two cases above both | ||
175 | * guarantee p points to at least nbytes bytes. | ||
176 | */ | ||
172 | memcpy(p, argp->p, avail); | 177 | memcpy(p, argp->p, avail); |
173 | /* step to next page */ | 178 | /* step to next page */ |
174 | argp->p = page_address(argp->pagelist[0]); | 179 | argp->p = page_address(argp->pagelist[0]); |