From patchwork Thu Aug 14 21:39:32 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Weston Andros Adamson X-Patchwork-Id: 4725531 Return-Path: X-Original-To: patchwork-linux-nfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 2F8A4C0338 for ; Thu, 14 Aug 2014 21:40:02 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 59A3D2013A for ; Thu, 14 Aug 2014 21:40:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 847C4201DD for ; Thu, 14 Aug 2014 21:40:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932122AbaHNVjn (ORCPT ); Thu, 14 Aug 2014 17:39:43 -0400 Received: from mail-ig0-f177.google.com ([209.85.213.177]:34313 "EHLO mail-ig0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932081AbaHNVjk (ORCPT ); Thu, 14 Aug 2014 17:39:40 -0400 Received: by mail-ig0-f177.google.com with SMTP id hn18so207817igb.10 for ; Thu, 14 Aug 2014 14:39:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-type:content-transfer-encoding; bh=hVzyu/y5Q3vD6/bhicHiz/L4Yr26qqpxprdUQ8Sa7WM=; b=eF/YTEnL3/uJZKfKz/lgVR5qS5YLMq6sHIgSDrHjbVxZRIR2JXZzGV9BcrqZUSqeZb PwZgdi0wRxe8NY2ozDHJf8PZF7qXKJTVQe525klhpAPCylOdDJFCZlJFHhqqgYZ6GNur pJvQO4BsW65hABAkiAg83+ByeopNQ45muzWFoSBzWw6yK/Uc+EqGDDkDRVZHasCQoAVJ ubLa7aWLsz/v57u7/Do2JFjrM5PRyxrj5JsGIYto2ml8qGWFS05HekCUaZrfCFfMZI0D N437fxSXMZa2BRsFeqqAZV/zmb4Sb5GKcNwELXD4dzD9bgtqGxioZ7bW+h25GBM/rPq/ AUgA== X-Gm-Message-State: ALoCoQlTB05XHuwDF37GaGzJhtohRsA8MvpgYJeVkOvu3honWanKf5EP9SyS3DZhHus9f8/lt60v X-Received: by 10.50.253.195 with SMTP id ac3mr21188770igd.18.1408052379998; Thu, 14 Aug 2014 14:39:39 -0700 (PDT) Received: from gavrio-wifi.robotsandstuff.fake (c-98-209-19-144.hsd1.mi.comcast.net. [98.209.19.144]) by mx.google.com with ESMTPSA id qd8sm254789igb.1.2014.08.14.14.39.39 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 14 Aug 2014 14:39:39 -0700 (PDT) From: Weston Andros Adamson To: linux-nfs@vger.kernel.org Cc: Weston Andros Adamson Subject: [PATCH 1/2] nfs: disallow duplicate pages in pgio page vectors Date: Thu, 14 Aug 2014 17:39:32 -0400 Message-Id: <1408052373-4306-2-git-send-email-dros@primarydata.com> X-Mailer: git-send-email 1.8.5.2 (Apple Git-48) In-Reply-To: <1408052373-4306-1-git-send-email-dros@primarydata.com> References: <1408052373-4306-1-git-send-email-dros@primarydata.com> MIME-Version: 1.0 Sender: linux-nfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org X-Spam-Status: No, score=-7.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Adjacent requests that share the same page are allowed, but should only use one entry in the page vector. This avoids overruning the page vector - it is sized based on how many bytes there are, not by request count. This fixes issues that manifest as "Redzone overwritten" bugs (the vector overrun) and hangs waiting on page read / write, as it waits on the same page more than once. This also adds bounds checking to the page vector with a graceful failure (WARN_ON_ONCE and pgio error returned to application). Reported-by: Toralf Förster Signed-off-by: Weston Andros Adamson --- fs/nfs/pagelist.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index e0c2e72..73476df 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c @@ -733,10 +733,11 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, struct nfs_pgio_header *hdr) { struct nfs_page *req; - struct page **pages; + struct page **pages, + *last_page; struct list_head *head = &desc->pg_list; struct nfs_commit_info cinfo; - unsigned int pagecount; + unsigned int pagecount, pageused; pagecount = nfs_page_array_len(desc->pg_base, desc->pg_count); if (!nfs_pgarray_set(&hdr->page_array, pagecount)) @@ -744,11 +745,26 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq); pages = hdr->page_array.pagevec; + last_page = NULL; + pageused = 0; while (!list_empty(head)) { req = nfs_list_entry(head->next); nfs_list_remove_request(req); nfs_list_add_request(req, &hdr->pages); - *pages++ = req->wb_page; + + if (pageused >= pagecount) { + WARN_ON_ONCE(1); + return nfs_pgio_error(desc, hdr); + } + + if (!last_page || last_page != req->wb_page) { + *pages++ = last_page = req->wb_page; + pageused++; + } + } + if (pageused != pagecount) { + WARN_ON_ONCE(1); + return nfs_pgio_error(desc, hdr); } if ((desc->pg_ioflags & FLUSH_COND_STABLE) &&