Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp2285900pxb; Thu, 11 Feb 2021 08:40:33 -0800 (PST) X-Google-Smtp-Source: ABdhPJxiCLsQh2muur1UD8IdSdTs1iDfnNY/RNTgCf4k9gAwVvwcX4OC+yzfByeqI+ApYE9Z/Tl2 X-Received: by 2002:a17:907:20e8:: with SMTP id rh8mr4608853ejb.119.1613061633771; Thu, 11 Feb 2021 08:40:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1613061633; cv=none; d=google.com; s=arc-20160816; b=JkeQMOwL8k5ycRXgZNiF1IVRe+fj4pL1ZGfaRQUmGQXu2QopuiHu8vIOAZ+/gDe5Sj sSDcIqcKpXJFeA09iuZauGX8zBg6lXbxKbV2nPdtphNPgNr0EgERcsKIDLRqdM+Y7GrV xDZ0wQJTfXKaMpWlpCHK6uDadSDg3ZjA4AsVzX/uTWfaycC4N7aKjTmDf+jYCK5EyNi1 JVfWClEgIdsIBzueV/LiYcB5NygEb9KFU+QKhOnrl+C2ZvYFA9TYKZytJA12Vwjmfvdl BCR/1Sblc9Pexu4vmDBhzuh3BCzWYEisdGE7n2UFlcCEpgmZNI9pGFbkmYel9LbbGY8x GZ2A== 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=9cSiiK2LmlAECy3aSRboRHOlU/u0DJFSpk9L6JgPZqY=; b=x5q+ZLuck43xFjIjODgXi2b9OFUCvbTtwG+ujNM52F3kpqHL3HDEpoDBLFHq53THLe 5Wlm9yBzaM55vfuC7J4zPMhu5lfMdDH7aQjYusRUeqoPGhCNQpwmgL3D1obhkl+K5PL2 6omWI764CiPvy6AO+fdb0viu08XIEGn/LO8OmlFSGTKCg8IUsep4BqNxD0YxI2/TAPpj VImQdZnyxIFw0ayFTu9YznEqwVZOUDfuJhgYx32TFHtc0E+YyMB70721L9QMG3QlIgoq PINfl/XBHWAnblWAc9TVb4TGvQOOzUBwBW9T3T6iJ/RAHjFBsVq5O+vcGBO3L854ZoAB kdwA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=AsTiR43o; 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 z19si4947248edr.191.2021.02.11.08.40.05; Thu, 11 Feb 2021 08:40:33 -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=AsTiR43o; 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 S232068AbhBKQiX (ORCPT + 99 others); Thu, 11 Feb 2021 11:38:23 -0500 Received: from mail.kernel.org ([198.145.29.99]:55778 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231424AbhBKPcA (ORCPT ); Thu, 11 Feb 2021 10:32:00 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 761CE64EFC; Thu, 11 Feb 2021 15:05:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1613055906; bh=cAgOBk3MyjaSix8dPcIOHbQDM9GJ5MFiu3LQh8rxwXA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=AsTiR43o9Gv6xZhPCv2VlQ2PnjADzU+Zg3gC/cENOjbjddrhM/82yFnG5WfuT5I8B Fnk/UNiTz5nEQqMoWeJwA2HEVAVVUIYZKpS0p16hj8f6uRBPIr8kTXtK5iW7zrGR2B y9EqeQT//ETZ51Jj9TYVkIVxC8P4gQwgOHIacVik= 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 5.10 53/54] squashfs: add more sanity checks in inode lookup Date: Thu, 11 Feb 2021 16:02:37 +0100 Message-Id: <20210211150155.181873848@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210211150152.885701259@linuxfoundation.org> References: <20210211150152.885701259@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 @@ -41,12 +41,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; @@ -111,7 +116,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); @@ -121,20 +129,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); }