Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp1776672imm; Thu, 27 Sep 2018 02:16:52 -0700 (PDT) X-Google-Smtp-Source: ACcGV63wAeibMLrMMqwEezV3DkpIcLfBOWQZXN+wKfTmx5PbfrsF80BQB0KegJPsgHCjnlqB1NpZ X-Received: by 2002:a63:646:: with SMTP id 67-v6mr8847454pgg.230.1538039811990; Thu, 27 Sep 2018 02:16:51 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1538039811; cv=none; d=google.com; s=arc-20160816; b=W+3qNgX8PVmcQdwjvoX/cI4DjmtDW+LWM76GLkeNK3UL3vu256Y3qwz+avfF/x/ZdC ZvlcXTPrsCgpy+/Da48ZQ2U/UYeBBQZ72P1wS2GDNRRt0hySsY4NQw2SFKbpqQiL8WV6 WMn/QX5ubTNuW9kJ09H6tgdLK+D0LOn35USmzWLuTnjHu8lvukZAf6BFb4TKpuppNYjG kmwTx2KE0zYsuEY9IhP5MT2dSryX27NkANLI5bG4Efd5sBqGvvciFduoSYHHWhdiQVQ+ lz8QdedAc3tqnnpneRAjN8fDL3LcABeg4GBYNoIF1uoTCyvJ02oODZGmTgI1j2/ifiCn J1YQ== 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=h/RV/CYMG3EQF/IcK0QSjMlZ3myyhGl0TmdqkXndJdo=; b=VgP8syGRSMO4j8stTOyRvqxSL0zpsZ4cROJl/M7oAwNfxKxNGEl4uIj0bbz9aJmjCK hZwulj9Am++D+wLDOlv+S+bCKOgJvb4qjHd4dOl2GR1VCJ2LcgQTRwMMH2imMCWrCyWd dFwX90U5ixWSvEjlTrK3qKoErOeuJ95OCrP/mvwBYsd6DwwOY7oF6jY9rA6Pf3ZFR7cJ YgtU7FrusnlVGEe1fUfEgkjmpO/5K+WuGZXkdkmiiOut2Wp52mZtNUyqvN/PCh/UWkLY sagp2vgQajPNKN70dGBYihmsUR+f1R26a/1dhv3U6YSLDpygT0k+bbwRd1ZB3nbiOHmY y21Q== 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 b27-v6si1489479pgb.156.2018.09.27.02.16.37; Thu, 27 Sep 2018 02:16:51 -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 S1728185AbeI0Pbo (ORCPT + 99 others); Thu, 27 Sep 2018 11:31:44 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:55518 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727354AbeI0Pbn (ORCPT ); Thu, 27 Sep 2018 11:31:43 -0400 Received: from localhost (ip-213-127-77-73.ip.prioritytelecom.net [213.127.77.73]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id C2A421117; Thu, 27 Sep 2018 09:14:25 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Theodore Tso , Wen Xu Subject: [PATCH 4.18 77/88] ext4: avoid divide by zero fault when deleting corrupted inline directories Date: Thu, 27 Sep 2018 11:03:58 +0200 Message-Id: <20180927090309.968088055@linuxfoundation.org> X-Mailer: git-send-email 2.19.0 In-Reply-To: <20180927090300.631426620@linuxfoundation.org> References: <20180927090300.631426620@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: Theodore Ts'o commit 4d982e25d0bdc83d8c64e66fdeca0b89240b3b85 upstream. A specially crafted file system can trick empty_inline_dir() into reading past the last valid entry in a inline directory, and then run into the end of xattr marker. This will trigger a divide by zero fault. Fix this by using the size of the inline directory instead of dir->i_size. Also clean up error reporting in __ext4_check_dir_entry so that the message is clearer and more understandable --- and avoids the division by zero trap if the size passed in is zero. (I'm not sure why we coded it that way in the first place; printing offset % size is actually more confusing and less useful.) https://bugzilla.kernel.org/show_bug.cgi?id=200933 Signed-off-by: Theodore Ts'o Reported-by: Wen Xu Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/dir.c | 20 +++++++++----------- fs/ext4/inline.c | 4 +++- 2 files changed, 12 insertions(+), 12 deletions(-) --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -76,7 +76,7 @@ int __ext4_check_dir_entry(const char *f else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len))) error_msg = "rec_len is too small for name_len"; else if (unlikely(((char *) de - buf) + rlen > size)) - error_msg = "directory entry across range"; + error_msg = "directory entry overrun"; else if (unlikely(le32_to_cpu(de->inode) > le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count))) error_msg = "inode out of bounds"; @@ -85,18 +85,16 @@ int __ext4_check_dir_entry(const char *f if (filp) ext4_error_file(filp, function, line, bh->b_blocknr, - "bad entry in directory: %s - offset=%u(%u), " - "inode=%u, rec_len=%d, name_len=%d", - error_msg, (unsigned) (offset % size), - offset, le32_to_cpu(de->inode), - rlen, de->name_len); + "bad entry in directory: %s - offset=%u, " + "inode=%u, rec_len=%d, name_len=%d, size=%d", + error_msg, offset, le32_to_cpu(de->inode), + rlen, de->name_len, size); else ext4_error_inode(dir, function, line, bh->b_blocknr, - "bad entry in directory: %s - offset=%u(%u), " - "inode=%u, rec_len=%d, name_len=%d", - error_msg, (unsigned) (offset % size), - offset, le32_to_cpu(de->inode), - rlen, de->name_len); + "bad entry in directory: %s - offset=%u, " + "inode=%u, rec_len=%d, name_len=%d, size=%d", + error_msg, offset, le32_to_cpu(de->inode), + rlen, de->name_len, size); return 1; } --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -1753,6 +1753,7 @@ bool empty_inline_dir(struct inode *dir, { int err, inline_size; struct ext4_iloc iloc; + size_t inline_len; void *inline_pos; unsigned int offset; struct ext4_dir_entry_2 *de; @@ -1780,8 +1781,9 @@ bool empty_inline_dir(struct inode *dir, goto out; } + inline_len = ext4_get_inline_size(dir); offset = EXT4_INLINE_DOTDOT_SIZE; - while (offset < dir->i_size) { + while (offset < inline_len) { de = ext4_get_inline_entry(dir, &iloc, offset, &inline_pos, &inline_size); if (ext4_check_dir_entry(dir, NULL, de,