diff options
author | Bryan Schumaker <bjschuma@netapp.com> | 2010-10-20 15:44:29 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-10-23 15:27:33 -0400 |
commit | babddc72a9468884ce1a23db3c3d54b0afa299f0 (patch) | |
tree | b176e5795b47c73c47543acdc546da0c38619ddc /fs/nfs/nfs2xdr.c | |
parent | ba8e452a4fe64a51b74d43761e14d99f0666cc45 (diff) |
NFS: decode_dirent should use an xdr_stream
Convert nfs*xdr.c to use an xdr stream in decode_dirent. This will prevent a
kernel oops that has been occuring when reading a vmapped page.
Signed-off-by: Bryan Schumaker <bjschuma@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs2xdr.c')
-rw-r--r-- | fs/nfs/nfs2xdr.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 79c74387a2fe..0210c752e743 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
@@ -500,25 +500,56 @@ err_unmap: | |||
500 | goto out; | 500 | goto out; |
501 | } | 501 | } |
502 | 502 | ||
503 | static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | ||
504 | { | ||
505 | dprintk("nfs: %s: prematurely hit end of receive buffer. " | ||
506 | "Remaining buffer length is %tu words.\n", | ||
507 | func, xdr->end - xdr->p); | ||
508 | } | ||
509 | |||
503 | __be32 * | 510 | __be32 * |
504 | nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) | 511 | nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, int plus) |
505 | { | 512 | { |
506 | if (!*p++) { | 513 | __be32 *p; |
507 | if (!*p) | 514 | p = xdr_inline_decode(xdr, 4); |
515 | if (unlikely(!p)) | ||
516 | goto out_overflow; | ||
517 | if (!ntohl(*p++)) { | ||
518 | p = xdr_inline_decode(xdr, 4); | ||
519 | if (unlikely(!p)) | ||
520 | goto out_overflow; | ||
521 | if (!ntohl(*p++)) | ||
508 | return ERR_PTR(-EAGAIN); | 522 | return ERR_PTR(-EAGAIN); |
509 | entry->eof = 1; | 523 | entry->eof = 1; |
510 | return ERR_PTR(-EBADCOOKIE); | 524 | return ERR_PTR(-EBADCOOKIE); |
511 | } | 525 | } |
512 | 526 | ||
527 | p = xdr_inline_decode(xdr, 8); | ||
528 | if (unlikely(!p)) | ||
529 | goto out_overflow; | ||
530 | |||
513 | entry->ino = ntohl(*p++); | 531 | entry->ino = ntohl(*p++); |
514 | entry->len = ntohl(*p++); | 532 | entry->len = ntohl(*p++); |
533 | |||
534 | p = xdr_inline_decode(xdr, entry->len + 4); | ||
535 | if (unlikely(!p)) | ||
536 | goto out_overflow; | ||
515 | entry->name = (const char *) p; | 537 | entry->name = (const char *) p; |
516 | p += XDR_QUADLEN(entry->len); | 538 | p += XDR_QUADLEN(entry->len); |
517 | entry->prev_cookie = entry->cookie; | 539 | entry->prev_cookie = entry->cookie; |
518 | entry->cookie = ntohl(*p++); | 540 | entry->cookie = ntohl(*p++); |
519 | entry->eof = !p[0] && p[1]; | 541 | |
542 | p = xdr_inline_peek(xdr, 8); | ||
543 | if (p != NULL) | ||
544 | entry->eof = !p[0] && p[1]; | ||
545 | else | ||
546 | entry->eof = 0; | ||
520 | 547 | ||
521 | return p; | 548 | return p; |
549 | |||
550 | out_overflow: | ||
551 | print_overflow_msg(__func__, xdr); | ||
552 | return ERR_PTR(-EIO); | ||
522 | } | 553 | } |
523 | 554 | ||
524 | /* | 555 | /* |