Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp2273784pxb; Thu, 11 Feb 2021 08:24:47 -0800 (PST) X-Google-Smtp-Source: ABdhPJzK4CNrqjweU8Q4Oxb6NKzDeci6Gn2gsUmV9VNVBF/8eHt/xCnn6Wo5GFV1OnSISo/Sjeul X-Received: by 2002:a05:6402:541:: with SMTP id i1mr9041489edx.36.1613060686971; Thu, 11 Feb 2021 08:24:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1613060686; cv=none; d=google.com; s=arc-20160816; b=KxmRFMQltaPjBRVtTZMa40gW12lr77MVCYIWn4Y2EJH9Hz0fy+RNDntwH7Ur3s/9Rm suIt31p6yvb9PD1RzhUtbBX3hzfVYYqXmUaR5eDfBQ0a3YHP2MBNJgh3YAO8jOokJBX1 kO8xPJRoICrL5iwN3oD8EQG/hdvcBZeiS7vscJ7ioyLKrrBkcyYW7xaHBsrXDoFe5fd0 oApxHK08ksS8BQHWzLMLQnLC8a+ikNSccGo/9L8mdyLDcga+gxid3qbecuyrq/E6Oon4 K6dZQijJ6Eq7JDoGk6hahU/R2i8XYAejzYssMaXKVRSQ5omlaJoap46mLfVu+/avjQ+A oG8A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=Wiw2Q4dCqfV2DI6RzDYB5Xcup05br5+kEtmENWNk598=; b=fjVQfSVczft7DLAYf7RJrS30oFEIMulxJLrMmA4Vmd7Npyi6Crl4Cbd86FnAy3DP+p WKN2KGaNOjvhEVB9WV7F+YJGTtycle8cNdsj/IjWL5vneEmM8hvXu37w3gtlXn33XlLS QqdTZKzcRLjSgVVSCmtQureJ9ebJYhB54prdY0rzFJFOMQ+cI96gHLtxnrpmGhLVS4/A yHlx6P91Y7hkIdRh1OYM+XBUdMkhsPbNE7Med9jM8ndh/cHq8VQ4hBPbEgjfr7hlSxf8 O+nCfTNGJH6wwKcBnfSTE3iewHhoctih26JgevaXF/Odjk/h3CmI4AoWL89vtPq+Ecci FQEQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=wE5wjbFo; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id y11si4000183edr.575.2021.02.11.08.24.05; Thu, 11 Feb 2021 08:24:46 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=wE5wjbFo; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231668AbhBKQV0 (ORCPT + 99 others); Thu, 11 Feb 2021 11:21:26 -0500 Received: from mail.kernel.org ([198.145.29.99]:53514 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230420AbhBKPWi (ORCPT ); Thu, 11 Feb 2021 10:22:38 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 3BBC264F2F; Thu, 11 Feb 2021 15:07:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1613056033; bh=BhlBmM9PvB9+77K7Gft8i7tI8VYhRgHqbl7IcVwNecU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=wE5wjbFogRpCH7dIMjHeM86nKr6kPJ72wWtbLiheyAia/vMco7aZ01rZKG0T6GVAz mDvhL6YpPOhu1csn8kUgKoUV8t7OKoDp4h9TYXcSAMDnH05QtVfJAKMlD84G0MeCXn yQuVZeU4IHofjVhQ+0qR/pCgakNMtiY0r5DQW0DM= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Phillip Lougher , syzbot+04419e3ff19d2970ea28@syzkaller.appspotmail.com, Andrew Morton , Linus Torvalds Subject: [PATCH 4.19 23/24] squashfs: add more sanity checks in inode lookup Date: Thu, 11 Feb 2021 16:02:57 +0100 Message-Id: <20210211150148.766179194@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210211150147.743660073@linuxfoundation.org> References: <20210211150147.743660073@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Phillip Lougher commit eabac19e40c095543def79cb6ffeb3a8588aaff4 upstream. Sysbot has reported an "slab-out-of-bounds read" error which has been identified as being caused by a corrupted "ino_num" value read from the inode. This could be because the metadata block is uncompressed, or because the "compression" bit has been corrupted (turning a compressed block into an uncompressed block). This patch adds additional sanity checks to detect this, and the following corruption. 1. It checks against corruption of the inodes count. This can either lead to a larger table to be read, or a smaller than expected table to be read. In the case of a too large inodes count, this would often have been trapped by the existing sanity checks, but this patch introduces a more exact check, which can identify too small values. 2. It checks the contents of the index table for corruption. [phillip@squashfs.org.uk: fix checkpatch issue] Link: https://lkml.kernel.org/r/527909353.754618.1612769948607@webmail.123-reg.co.uk Link: https://lkml.kernel.org/r/20210204130249.4495-4-phillip@squashfs.org.uk Signed-off-by: Phillip Lougher Reported-by: syzbot+04419e3ff19d2970ea28@syzkaller.appspotmail.com Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- fs/squashfs/export.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) --- a/fs/squashfs/export.c +++ b/fs/squashfs/export.c @@ -54,12 +54,17 @@ static long long squashfs_inode_lookup(s struct squashfs_sb_info *msblk = sb->s_fs_info; int blk = SQUASHFS_LOOKUP_BLOCK(ino_num - 1); int offset = SQUASHFS_LOOKUP_BLOCK_OFFSET(ino_num - 1); - u64 start = le64_to_cpu(msblk->inode_lookup_table[blk]); + u64 start; __le64 ino; int err; TRACE("Entered squashfs_inode_lookup, inode_number = %d\n", ino_num); + if (ino_num == 0 || (ino_num - 1) >= msblk->inodes) + return -EINVAL; + + start = le64_to_cpu(msblk->inode_lookup_table[blk]); + err = squashfs_read_metadata(sb, &ino, &start, &offset, sizeof(ino)); if (err < 0) return err; @@ -124,7 +129,10 @@ __le64 *squashfs_read_inode_lookup_table u64 lookup_table_start, u64 next_table, unsigned int inodes) { unsigned int length = SQUASHFS_LOOKUP_BLOCK_BYTES(inodes); + unsigned int indexes = SQUASHFS_LOOKUP_BLOCKS(inodes); + int n; __le64 *table; + u64 start, end; TRACE("In read_inode_lookup_table, length %d\n", length); @@ -134,20 +142,37 @@ __le64 *squashfs_read_inode_lookup_table if (inodes == 0) return ERR_PTR(-EINVAL); - /* length bytes should not extend into the next table - this check - * also traps instances where lookup_table_start is incorrectly larger - * than the next table start + /* + * The computed size of the lookup table (length bytes) should exactly + * match the table start and end points */ - if (lookup_table_start + length > next_table) + if (length != (next_table - lookup_table_start)) return ERR_PTR(-EINVAL); table = squashfs_read_table(sb, lookup_table_start, length); + if (IS_ERR(table)) + return table; /* - * table[0] points to the first inode lookup table metadata block, - * this should be less than lookup_table_start + * table0], table[1], ... table[indexes - 1] store the locations + * of the compressed inode lookup blocks. Each entry should be + * less than the next (i.e. table[0] < table[1]), and the difference + * between them should be SQUASHFS_METADATA_SIZE or less. + * table[indexes - 1] should be less than lookup_table_start, and + * again the difference should be SQUASHFS_METADATA_SIZE or less */ - if (!IS_ERR(table) && le64_to_cpu(table[0]) >= lookup_table_start) { + for (n = 0; n < (indexes - 1); n++) { + start = le64_to_cpu(table[n]); + end = le64_to_cpu(table[n + 1]); + + if (start >= end || (end - start) > SQUASHFS_METADATA_SIZE) { + kfree(table); + return ERR_PTR(-EINVAL); + } + } + + start = le64_to_cpu(table[indexes - 1]); + if (start >= lookup_table_start || (lookup_table_start - start) > SQUASHFS_METADATA_SIZE) { kfree(table); return ERR_PTR(-EINVAL); }