Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp725618imm; Thu, 13 Sep 2018 06:53:27 -0700 (PDT) X-Google-Smtp-Source: ANB0VdYmWZdOFxeVLBZyklquiuH+2eRaWJi6aXW61cD6MyENhkBS22C1/ReIEywoDuzg1DM+COyn X-Received: by 2002:a63:7a45:: with SMTP id j5-v6mr7014617pgn.363.1536846807195; Thu, 13 Sep 2018 06:53:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1536846807; cv=none; d=google.com; s=arc-20160816; b=Cl1mEV3IipV4VNkkpMQNLJXWLtRRcdPKYOI2I/qNiO6LrBCEkaVDZkYq2Yhg79vajH bnDvL4ljBAZ8TWm/l0l7MgFl24Z90f4SpPyrdtHkP2w0uj9K83T0MBn22Yv9JRd+ovcU BMdwGd/rgwGYzEP323bcFx6TJW95DGeTusgEZMqi+QA/rC6yCRS1mo70Rb/B8uCXfLIZ rnfGIdTryvTCvvKX7VF1aMBQIQKSi+M0iiwuTIw1voR7ogLAfYPUEtLxkSvFXEviKIjJ 8v2OLAivuYmRGsxCqgqclOzz8qx96F1Va9h628+2YpidgZhVEezSIcd1Trcf2da+sl+F b9wQ== 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=N2qy6B1vl/o/U8y10G9yp96Z3u5IqCFmLZYpRHe74pw=; b=hLGc+paLtLN6n/PzTM6SziXn8989f4H80+CRt5VXOE+rGOsV+4JXhjpv0WxuJy0eYV gjIGPavLJ3+y/CVe5BSVu/1rgjAPCNxOZM3vJ4f0g87Mh1eQyUSdJHCMswBEU658cGPO 6L5T17/E4HgQOKgIwpULojPwO+G9o7V4Jerw6YoK2RWOJ+RvhBjK0m4VA2qkbT8N5lZF kDw0iE9AnmQD8hrR55u062j2VAO+bPvWzK6L5lA11/iBwvGvQFbxfytMIhW9co1y0c0q SIcF4Zi0ZpZ0JYaych3e6oFTWJr4/BE9WN6meWy3PjNwaQ79+7R9S7SiiTIvwG+33Exd sJ3A== 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 a20-v6si3706965pgv.85.2018.09.13.06.53.11; Thu, 13 Sep 2018 06:53:27 -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 S1731066AbeIMTCj (ORCPT + 99 others); Thu, 13 Sep 2018 15:02:39 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:33622 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730002AbeIMTCj (ORCPT ); Thu, 13 Sep 2018 15:02:39 -0400 Received: from localhost (ip-213-127-77-73.ip.prioritytelecom.net [213.127.77.73]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id B9ECCCE7; Thu, 13 Sep 2018 13:53:02 +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.18 048/197] fat: validate ->i_start before using Date: Thu, 13 Sep 2018 15:29:57 +0200 Message-Id: <20180913131843.462969256@linuxfoundation.org> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20180913131841.568116777@linuxfoundation.org> References: <20180913131841.568116777@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.18-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;