From patchwork Tue Mar 22 21:36:35 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vitaliy Gusev X-Patchwork-Id: 653631 X-Patchwork-Delegate: Trond.Myklebust@netapp.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p2MLqHlL010617 for ; Tue, 22 Mar 2011 21:52:19 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755542Ab1CVVwP (ORCPT ); Tue, 22 Mar 2011 17:52:15 -0400 Received: from relay03.bluemeaney.com ([205.234.16.187]:47196 "EHLO relay03.bluemeaney.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755324Ab1CVVwP (ORCPT ); Tue, 22 Mar 2011 17:52:15 -0400 X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Tue, 22 Mar 2011 21:52:19 +0000 (UTC) X-Greylist: delayed 924 seconds by postgrey-1.27 at vger.kernel.org; Tue, 22 Mar 2011 17:52:15 EDT X-ASG-Debug-ID: 1300829810-25ab947f0001-suBQlS Received: from sfdc-fe01.bluemeaney.com ([172.28.16.33]) by relay03.bluemeaney.com with ESMTP id KqBkmIIo6XnnLNsm; Tue, 22 Mar 2011 14:36:50 -0700 (PDT) X-Barracuda-Envelope-From: Gusev.Vitaliy@nexenta.com X-ASG-Whitelist: Client Received: from vT510 ([172.28.16.12]) by sfdc-fe01.bluemeaney.com with Microsoft SMTPSVC(6.0.3790.3959); Tue, 22 Mar 2011 14:36:48 -0700 From: Vitaliy Gusev X-Barracuda-BBL-IP: 172.28.16.12 X-Barracuda-RBL-IP: 172.28.16.12 To: Trond Myklebust Cc: linux-nfs@vger.kernel.org, Vitaliy Gusev Subject: [PATCH] nfs4: Fix memory corruption due to not expected FS_LOCATIONS v3 Date: Wed, 23 Mar 2011 00:36:35 +0300 X-ASG-Orig-Subj: [PATCH] nfs4: Fix memory corruption due to not expected FS_LOCATIONS v3 Message-Id: <1300829795-17054-1-git-send-email-gusev.vitaliy@nexenta.com> X-Mailer: git-send-email 1.7.1 X-OriginalArrivalTime: 22 Mar 2011 21:36:49.0785 (UTC) FILETIME=[407FB690:01CBE8D9] X-Barracuda-Connect: UNKNOWN[172.28.16.33] X-Barracuda-Start-Time: 1300829810 X-Barracuda-URL: http://spam.bluemeaney.com:8000/cgi-mod/mark.cgi X-Virus-Scanned: by bsmtpd at bluemeaney.com Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c87e543..6fea9c9 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -3451,7 +3451,8 @@ out_overflow: return -EIO; } -static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res) +static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res, + uint32_t *deny_bitmap) { int n; __be32 *p; @@ -3462,6 +3463,13 @@ static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, st status = 0; if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS))) goto out; + + if (unlikely(deny_bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)) { + status = -EIO; + printk(KERN_WARNING "%s: Unexpected fs_locations\n", __func__); + goto out; + } + dprintk("%s: fsroot ", __func__); status = decode_pathname(xdr, &res->fs_path); if (unlikely(status != 0)) @@ -4186,7 +4194,8 @@ xdr_error: static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fattr *fattr, struct nfs_fh *fh, - const struct nfs_server *server, int may_sleep) + const struct nfs_server *server, int may_sleep, + uint32_t *deny_bitmap) { int status; umode_t fmode = 0; @@ -4232,7 +4241,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr, struct nfs4_fs_locations, - fattr)); + fattr), deny_bitmap); if (status < 0) goto xdr_error; fattr->valid |= status; @@ -4301,11 +4310,13 @@ xdr_error: } static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, - struct nfs_fh *fh, const struct nfs_server *server, int may_sleep) + struct nfs_fh *fh, const struct nfs_server *server, int may_sleep, + int expect_fsloc) { __be32 *savep; uint32_t attrlen, bitmap[3] = {0}; + uint32_t deny_bitmap[3] = {0}; int status; status = decode_op_hdr(xdr, OP_GETATTR); @@ -4316,11 +4327,15 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat if (status < 0) goto xdr_error; + if (!expect_fsloc) + deny_bitmap[0] |= FATTR4_WORD0_FS_LOCATIONS; + status = decode_attr_length(xdr, &attrlen, &savep); if (status < 0) goto xdr_error; - status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep); + status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep, + deny_bitmap); if (status < 0) goto xdr_error; @@ -4333,7 +4348,7 @@ xdr_error: static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, const struct nfs_server *server, int may_sleep) { - return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep); + return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep, 0); } /* @@ -6338,9 +6353,11 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, if (status) goto out; xdr_enter_page(xdr, PAGE_SIZE); - status = decode_getfattr(xdr, &res->fs_locations->fattr, + status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, + NULL, res->fs_locations->server, - !RPC_IS_ASYNC(req->rq_task)); + !RPC_IS_ASYNC(req->rq_task), + 1); out: return status; } @@ -6639,7 +6656,7 @@ out: int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, int plus) { - uint32_t bitmap[3] = {0}; + uint32_t bitmap[3] = {0}, deny_bitmap[3] = {0}; uint32_t len; __be32 *p = xdr_inline_decode(xdr, 4); if (unlikely(!p)) @@ -6680,8 +6697,10 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, if (decode_attr_length(xdr, &len, &p) < 0) goto out_overflow; + deny_bitmap[0] |= FATTR4_WORD0_FS_LOCATIONS; + if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, - entry->server, 1) < 0) + entry->server, 1, deny_bitmap) < 0) goto out_overflow; if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) entry->ino = entry->fattr->fileid;