diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-03-31 17:02:02 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-04-08 21:06:50 -0400 |
commit | daeba89d43af0fa469d38a4ccdc32fff8ca17c2e (patch) | |
tree | 1c228b639571866d492e7ab8d5b843e41a955970 /net/sunrpc/xdr.c | |
parent | 7180c4c9e09888db0a188f729c96c6d7bd61fa83 (diff) | |
download | op-kernel-dev-daeba89d43af0fa469d38a4ccdc32fff8ca17c2e.zip op-kernel-dev-daeba89d43af0fa469d38a4ccdc32fff8ca17c2e.tar.gz |
SUNRPC: don't call flush_dcache_page() with an invalid pointer
Fix a problem in _copy_to_pages(), whereby it may call flush_dcache_page()
with an invalid pointer due to the fact that 'pgto' gets incremented
beyond the end of the page array. Fix is to exit the loop without this
unnecessary increment of pgto.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/xdr.c')
-rw-r--r-- | net/sunrpc/xdr.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 995c3fd..79a55d5 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -244,7 +244,7 @@ _copy_to_pages(struct page **pages, size_t pgbase, const char *p, size_t len) pgto = pages + (pgbase >> PAGE_CACHE_SHIFT); pgbase &= ~PAGE_CACHE_MASK; - do { + for (;;) { copy = PAGE_CACHE_SIZE - pgbase; if (copy > len) copy = len; @@ -253,6 +253,10 @@ _copy_to_pages(struct page **pages, size_t pgbase, const char *p, size_t len) memcpy(vto + pgbase, p, copy); kunmap_atomic(vto, KM_USER0); + len -= copy; + if (len == 0) + break; + pgbase += copy; if (pgbase == PAGE_CACHE_SIZE) { flush_dcache_page(*pgto); @@ -260,8 +264,7 @@ _copy_to_pages(struct page **pages, size_t pgbase, const char *p, size_t len) pgto++; } p += copy; - - } while ((len -= copy) != 0); + } flush_dcache_page(*pgto); } |