From patchwork Fri Mar 4 21:09:20 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Horman X-Patchwork-Id: 610241 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 p24L9gqw024457 for ; Fri, 4 Mar 2011 21:09:42 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932550Ab1CDVJl (ORCPT ); Fri, 4 Mar 2011 16:09:41 -0500 Received: from charlotte.tuxdriver.com ([70.61.120.58]:48347 "EHLO smtp.tuxdriver.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932509Ab1CDVJl (ORCPT ); Fri, 4 Mar 2011 16:09:41 -0500 Received: from hmsreliant.think-freely.org ([2001:470:8:a08:2d0:b7ff:fecc:e1e4] helo=localhost) by smtp.tuxdriver.com with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.63) (envelope-from ) id 1PvcFk-0001Sc-RK; Fri, 04 Mar 2011 16:09:38 -0500 From: Neil Horman To: linux-nfs@vger.kernel.org Cc: Neil Horman , Trond Myklebust , security@kernel.org, Jeff Layton Subject: [PATCH] nfs4: Ensure that ACL pages sent over NFS were not allocated from the slab (v2) Date: Fri, 4 Mar 2011 16:09:20 -0500 Message-Id: <1299272960-16582-1-git-send-email-nhorman@tuxdriver.com> X-Mailer: git-send-email 1.7.4 In-Reply-To: <1299266730.2901.15.camel@heimdal.trondhjem.org> References: <1299266730.2901.15.camel@heimdal.trondhjem.org> X-Spam-Score: -2.6 (--) X-Spam-Status: No Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Fri, 04 Mar 2011 21:09:42 +0000 (UTC) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 78936a8..6e906af 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -51,6 +51,7 @@ #include #include #include +#include #include "nfs4_fs.h" #include "delegation.h" @@ -3252,6 +3253,36 @@ static void buf_to_pages(const void *buf, size_t buflen, } } +static int buf_to_pages_noslab(const void *buf, size_t buflen, + struct page **pages, unsigned int *pgbase) +{ + struct page *newpage, **spages; + int rc = 0; + size_t len; + spages = pages; + + do { + len = min(PAGE_CACHE_SIZE, buflen); + newpage = alloc_page(GFP_KERNEL); + + if (newpage == NULL) + goto unwind; + memcpy(page_address(newpage), buf, len); + buf += len; + buflen -= len; + *(pages++) = newpage; + rc++; + } while (buflen != 0); + + *pgbase = 0; + return rc; + +unwind: + for(; rc > 0; rc--) + __free_page(spages[rc-1]); + return -ENOMEM; +} + struct nfs4_cached_acl { int cached; size_t len; @@ -3420,13 +3451,23 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl .rpc_argp = &arg, .rpc_resp = &res, }; - int ret; + int ret, i; if (!nfs4_server_supports_acls(server)) return -EOPNOTSUPP; + i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase); + if (i < 0) + return i; nfs_inode_return_delegation(inode); - buf_to_pages(buf, buflen, arg.acl_pages, &arg.acl_pgbase); ret = nfs4_call_sync(server, &msg, &arg, &res, 1); + + /* + * Free each page after tx, so the only ref left is + * held by the network stack + */ + for (; i > 0; i--) + put_page(pages[i-1]); + /* * Acl update can result in inode attribute update. * so mark the attribute cache invalid.