From patchwork Thu Jul 11 14:00:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kara X-Patchwork-Id: 11040023 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8545F14F6 for ; Thu, 11 Jul 2019 14:00:20 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 772AB287EF for ; Thu, 11 Jul 2019 14:00:20 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6B03A288CA; Thu, 11 Jul 2019 14:00:20 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BE74228846 for ; Thu, 11 Jul 2019 14:00:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728386AbfGKOAS (ORCPT ); Thu, 11 Jul 2019 10:00:18 -0400 Received: from mx2.suse.de ([195.135.220.15]:51082 "EHLO mx1.suse.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1728102AbfGKOAS (ORCPT ); Thu, 11 Jul 2019 10:00:18 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.220.254]) by mx1.suse.de (Postfix) with ESMTP id F3AB4AF57; Thu, 11 Jul 2019 14:00:16 +0000 (UTC) Received: by quack2.suse.cz (Postfix, from userid 1000) id 2E77A1E43CE; Thu, 11 Jul 2019 16:00:16 +0200 (CEST) From: Jan Kara To: Cc: , , Amir Goldstein , Boaz Harrosh , Jan Kara , stable@vger.kernel.org Subject: [PATCH 3/3] xfs: Fix stale data exposure when readahead races with hole punch Date: Thu, 11 Jul 2019 16:00:12 +0200 Message-Id: <20190711140012.1671-4-jack@suse.cz> X-Mailer: git-send-email 2.16.4 In-Reply-To: <20190711140012.1671-1-jack@suse.cz> References: <20190711140012.1671-1-jack@suse.cz> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Hole puching currently evicts pages from page cache and then goes on to remove blocks from the inode. This happens under both XFS_IOLOCK_EXCL and XFS_MMAPLOCK_EXCL which provides appropriate serialization with racing reads or page faults. However there is currently nothing that prevents readahead triggered by fadvise() or madvise() from racing with the hole punch and instantiating page cache page after hole punching has evicted page cache in xfs_flush_unmap_range() but before it has removed blocks from the inode. This page cache page will be mapping soon to be freed block and that can lead to returning stale data to userspace or even filesystem corruption. Fix the problem by protecting handling of readahead requests by XFS_IOLOCK_SHARED similarly as we protect reads. CC: stable@vger.kernel.org Link: https://lore.kernel.org/linux-fsdevel/CAOQ4uxjQNmxqmtA_VbYW0Su9rKRk2zobJmahcyeaEVOFKVQ5dw@mail.gmail.com/ Reported-by: Amir Goldstein Signed-off-by: Jan Kara --- fs/xfs/xfs_file.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 76748255f843..88fe3dbb3ba2 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -33,6 +33,7 @@ #include #include #include +#include static const struct vm_operations_struct xfs_file_vm_ops; @@ -939,6 +940,24 @@ xfs_file_fallocate( return error; } +STATIC int +xfs_file_fadvise( + struct file *file, + loff_t start, + loff_t end, + int advice) +{ + struct xfs_inode *ip = XFS_I(file_inode(file)); + int ret; + + /* Readahead needs protection from hole punching and similar ops */ + if (advice == POSIX_FADV_WILLNEED) + xfs_ilock(ip, XFS_IOLOCK_SHARED); + ret = generic_fadvise(file, start, end, advice); + if (advice == POSIX_FADV_WILLNEED) + xfs_iunlock(ip, XFS_IOLOCK_SHARED); + return ret; +} STATIC loff_t xfs_file_remap_range( @@ -1235,6 +1254,7 @@ const struct file_operations xfs_file_operations = { .fsync = xfs_file_fsync, .get_unmapped_area = thp_get_unmapped_area, .fallocate = xfs_file_fallocate, + .fadvise = xfs_file_fadvise, .remap_file_range = xfs_file_remap_range, };