aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorSachin Prabhu <sprabhu@redhat.com>2012-04-17 09:35:39 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-04-27 13:15:07 -0400
commit5a00689930ab975fdd1b37b034475017e460cf2a (patch)
tree9cc6df10ac849488efe28ea811e55c213c22a754 /fs/nfs/nfs4proc.c
parent10bd295a0b6488ebe634b72a11d8986bd3af3819 (diff)
Avoid reading past buffer when calling GETACL
Bug noticed in commit bf118a342f10dafe44b14451a1392c3254629a1f When calling GETACL, if the size of the bitmap array, the length attribute and the acl returned by the server is greater than the allocated buffer(args.acl_len), we can Oops with a General Protection fault at _copy_from_pages() when we attempt to read past the pages allocated. This patch allocates an extra PAGE for the bitmap and checks to see that the bitmap + attribute_length + ACLs don't exceed the buffer space allocated to it. Signed-off-by: Sachin Prabhu <sprabhu@redhat.com> Reported-by: Jian Li <jiali@redhat.com> [Trond: Fixed a size_t vs unsigned int printk() warning] Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c16
1 files changed, 10 insertions, 6 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 60d5f4c26dda..f5f125fdae1b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3684,19 +3684,23 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
3684 if (npages == 0) 3684 if (npages == 0)
3685 npages = 1; 3685 npages = 1;
3686 3686
3687 /* Add an extra page to handle the bitmap returned */
3688 npages++;
3689
3687 for (i = 0; i < npages; i++) { 3690 for (i = 0; i < npages; i++) {
3688 pages[i] = alloc_page(GFP_KERNEL); 3691 pages[i] = alloc_page(GFP_KERNEL);
3689 if (!pages[i]) 3692 if (!pages[i])
3690 goto out_free; 3693 goto out_free;
3691 } 3694 }
3692 if (npages > 1) { 3695
3693 /* for decoding across pages */ 3696 /* for decoding across pages */
3694 res.acl_scratch = alloc_page(GFP_KERNEL); 3697 res.acl_scratch = alloc_page(GFP_KERNEL);
3695 if (!res.acl_scratch) 3698 if (!res.acl_scratch)
3696 goto out_free; 3699 goto out_free;
3697 } 3700
3698 args.acl_len = npages * PAGE_SIZE; 3701 args.acl_len = npages * PAGE_SIZE;
3699 args.acl_pgbase = 0; 3702 args.acl_pgbase = 0;
3703
3700 /* Let decode_getfacl know not to fail if the ACL data is larger than 3704 /* Let decode_getfacl know not to fail if the ACL data is larger than
3701 * the page we send as a guess */ 3705 * the page we send as a guess */
3702 if (buf == NULL) 3706 if (buf == NULL)