Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp714705imm; Thu, 13 Sep 2018 06:43:29 -0700 (PDT) X-Google-Smtp-Source: ANB0Vdbvmptec3M0ucmUwx7PQCZnYao4f3Z4M+jdWRpyht4zk+WTqCU39K4z0MuSJ6cKDOJNVUNc X-Received: by 2002:aa7:82c3:: with SMTP id f3-v6mr7726652pfn.136.1536846208978; Thu, 13 Sep 2018 06:43:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536846208; cv=none; d=google.com; s=arc-20160816; b=I/dZJ2cL5+bm+Ry0jgXddcQXgaQ22rbVhZ0Ut0bhEb3J286y9CEJZaQtlYBZXQVH2P CjGLo2hBCIgvbtwcPJQE6KXeu+vbbOEC8ItihS7Ake/sKlun9xzd8i2zOo6X72T5yJ2f HJUVTwE5aW/4NQzLpQnN0exnbIFIcvksnXZ2xF3YISx2pRJkvL+mr+OokIM8323nf03k wIiIEJWb/uw38ySituWU2qInnLHcaR8dY2/4fxPJ5/D/MnVk5/mRY/9zBx6JYm7S5CMM h1L2OSacsYItHVm0S1NZMObOFmuPFuZSEoYGL9WMnzyJtu355mGHpwcVH9FwK67hPrwv /eRg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from; bh=cLLptV6q71uRwDDbya86L/O01pskuUStMHIbrUcqCMM=; b=Yv8qA7DiVPxsLefdX31KPrKR3Be51hm6uGxFM1lDOGWPx4849NRegtBKX3SSsouCfi PJrwNOjGots22+0OkAgp7C6QVr30cXXuxbocqd8WXi/uKNPFdMbxSXAwwonmIrjeM5PS fDIT4EilG1WureNvnWzP+t5Qk6kxfvkKc+6Ar7XTKWO/NDl1XHaHtnPwjT3Y+jwgqL3A PmGcv2KzUL5pOhLTUXm/QoVyfDnPIstrOT3DK5XT5ttfitfJtF2pTCX7pSan/WQhmoJ8 3sFTovI7Jd5r6YWCKL6FRybrBueqqUkIvmVtkuQzUZKI3bMoPRBYBVt4YJyEDSwEUaZN xCnA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b18-v6si4334822pgb.612.2018.09.13.06.43.14; Thu, 13 Sep 2018 06:43:28 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729050AbeIMSw1 (ORCPT + 99 others); Thu, 13 Sep 2018 14:52:27 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:60268 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727231AbeIMSw1 (ORCPT ); Thu, 13 Sep 2018 14:52:27 -0400 Received: from localhost (ip-213-127-77-73.ip.prioritytelecom.net [213.127.77.73]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 6BA19D10; Thu, 13 Sep 2018 13:42:54 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, OGAWA Hirofumi , Anatoly Trosinenko , Alan Cox , Al Viro , Andrew Morton , Linus Torvalds , Sasha Levin Subject: [PATCH 4.14 029/115] fat: validate ->i_start before using Date: Thu, 13 Sep 2018 15:30:49 +0200 Message-Id: <20180913131825.430223092@linuxfoundation.org> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20180913131823.327472833@linuxfoundation.org> References: <20180913131823.327472833@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: OGAWA Hirofumi [ Upstream commit 0afa9626667c3659ef8bd82d42a11e39fedf235c ] On corrupted FATfs may have invalid ->i_start. To handle it, this checks ->i_start before using, and return proper error code. Link: http://lkml.kernel.org/r/87o9f8y1t5.fsf_-_@mail.parknet.co.jp Signed-off-by: OGAWA Hirofumi Reported-by: Anatoly Trosinenko Tested-by: Anatoly Trosinenko Cc: Alan Cox Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/fat/cache.c | 19 ++++++++++++------- fs/fat/fat.h | 5 +++++ fs/fat/fatent.c | 6 +++--- 3 files changed, 20 insertions(+), 10 deletions(-) --- a/fs/fat/cache.c +++ b/fs/fat/cache.c @@ -225,7 +225,8 @@ static inline void cache_init(struct fat int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus) { struct super_block *sb = inode->i_sb; - const int limit = sb->s_maxbytes >> MSDOS_SB(sb)->cluster_bits; + struct msdos_sb_info *sbi = MSDOS_SB(sb); + const int limit = sb->s_maxbytes >> sbi->cluster_bits; struct fat_entry fatent; struct fat_cache_id cid; int nr; @@ -234,6 +235,12 @@ int fat_get_cluster(struct inode *inode, *fclus = 0; *dclus = MSDOS_I(inode)->i_start; + if (!fat_valid_entry(sbi, *dclus)) { + fat_fs_error_ratelimit(sb, + "%s: invalid start cluster (i_pos %lld, start %08x)", + __func__, MSDOS_I(inode)->i_pos, *dclus); + return -EIO; + } if (cluster == 0) return 0; @@ -250,9 +257,8 @@ int fat_get_cluster(struct inode *inode, /* prevent the infinite loop of cluster chain */ if (*fclus > limit) { fat_fs_error_ratelimit(sb, - "%s: detected the cluster chain loop" - " (i_pos %lld)", __func__, - MSDOS_I(inode)->i_pos); + "%s: detected the cluster chain loop (i_pos %lld)", + __func__, MSDOS_I(inode)->i_pos); nr = -EIO; goto out; } @@ -262,9 +268,8 @@ int fat_get_cluster(struct inode *inode, goto out; else if (nr == FAT_ENT_FREE) { fat_fs_error_ratelimit(sb, - "%s: invalid cluster chain (i_pos %lld)", - __func__, - MSDOS_I(inode)->i_pos); + "%s: invalid cluster chain (i_pos %lld)", + __func__, MSDOS_I(inode)->i_pos); nr = -EIO; goto out; } else if (nr == FAT_ENT_EOF) { --- a/fs/fat/fat.h +++ b/fs/fat/fat.h @@ -348,6 +348,11 @@ static inline void fatent_brelse(struct fatent->fat_inode = NULL; } +static inline bool fat_valid_entry(struct msdos_sb_info *sbi, int entry) +{ + return FAT_START_ENT <= entry && entry < sbi->max_cluster; +} + extern void fat_ent_access_init(struct super_block *sb); extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent, int entry); --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c @@ -23,7 +23,7 @@ static void fat12_ent_blocknr(struct sup { struct msdos_sb_info *sbi = MSDOS_SB(sb); int bytes = entry + (entry >> 1); - WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry); + WARN_ON(!fat_valid_entry(sbi, entry)); *offset = bytes & (sb->s_blocksize - 1); *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits); } @@ -33,7 +33,7 @@ static void fat_ent_blocknr(struct super { struct msdos_sb_info *sbi = MSDOS_SB(sb); int bytes = (entry << sbi->fatent_shift); - WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry); + WARN_ON(!fat_valid_entry(sbi, entry)); *offset = bytes & (sb->s_blocksize - 1); *blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits); } @@ -353,7 +353,7 @@ int fat_ent_read(struct inode *inode, st int err, offset; sector_t blocknr; - if (entry < FAT_START_ENT || sbi->max_cluster <= entry) { + if (!fat_valid_entry(sbi, entry)) { fatent_brelse(fatent); fat_fs_error(sb, "invalid access to FAT (entry 0x%08x)", entry); return -EIO;