From nobody Mon Jun 8 08:27:59 2026 Received: from mail-qv1-f48.google.com (mail-qv1-f48.google.com [209.85.219.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E45C0346A1E for ; Wed, 3 Jun 2026 17:26:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780507594; cv=none; b=luF3cKsh4qAoHtFhd+qSD5DqA+3aEUcLzQbNVKtcw8Ew1yQgg2Vty7Dd3S0dOz7NQG3tVVUTt29fNyOE9GDqLnD3QxnBT8iLVKnanFb+anZpQ6fciWgaWvgLeoNQ4iEf7D3QfSgy161m/0VGP5CBf2bL9F9wsSpORozZhGIJEEg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780507594; c=relaxed/simple; bh=QgX8B6xNnMAm+k6np2suW6NDL5I5JceVZckrMAITzEE=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=GIOYH9QKNP22rScNNsQCZA9L23FdGk1dJbGoQIPYDi8y/B+N/3tQPz1pESTTh9WrAgjeeEqjRqAGMAC+TJejEAXxVwIelUAn8Q2miB0OECAlk+NLAsAHzvFrniGWanLWlzo1+hfFrCnbqECHjPscYbj6rvcZQbWfZHKOxBdrdYc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=trailofbits.com; spf=pass smtp.mailfrom=trailofbits.com; dkim=pass (2048-bit key) header.d=trailofbits.com header.i=@trailofbits.com header.b=SVntOE1+; arc=none smtp.client-ip=209.85.219.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=trailofbits.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=trailofbits.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=trailofbits.com header.i=@trailofbits.com header.b="SVntOE1+" Received: by mail-qv1-f48.google.com with SMTP id 6a1803df08f44-8ccf6a63a45so56163656d6.3 for ; Wed, 03 Jun 2026 10:26:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=trailofbits.com; s=google; t=1780507592; x=1781112392; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=hS+Ky8TEecnXm3m0M6v3zCgsDb7VsbQ7m46ppg66wxU=; b=SVntOE1+ldwuyPeX+HxOwmYBLIlSs8ptotZpE0RW6TtKWadsPIjTw5WNXvYWRK0FZ5 VmeglXapR3+YEJhgKhGOrMR6XR9Cld4QslfRRPDW47qUbNfqa0PTWRFv01yJIenv2y3I fqAP0Panj67LdtziHNgVEP7VgwWOxVmTcBzkB/qfpBvoo4FLtdJbb6hx8JkzUXyshKL6 Z0Y5sXAjpQRKfH0X/XLQWkqPTie5QVCY8Ql8YEeuCPuXxlz+iLWPKtknCirTNgR9KueA xcwdbq0nLBKTfJrw3ElFSEAyia2w/HrWTBu2w/j710v5/dXHKzmSCcM1nzN2EzDPCki0 spWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1780507592; x=1781112392; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=hS+Ky8TEecnXm3m0M6v3zCgsDb7VsbQ7m46ppg66wxU=; b=EnI/z5lWj0c51MaQl2Nrn1BLJhYuScvHMCxz2SC5pdAloYBLsWQ2HIKHVwgOKYTycD 527Rbe+9ed/Lur9avMIy1wgJhGvqMVz5cLAlstrA+9FggPN8tX6nnJJICA7mCiJpz5YJ X8iU3yw+NOvt/5ueWNEl7JnLhGiP+hunGyFFxYhqeHnFLMfCOnF2r+V0ov76etPYa2F/ tFVNyn9+u0cq31fRwVo0ZoruVjyfKbzJYr4ci1AZigmbF4eVJWJWNzFj0VkNrEDg3Y26 m0KmjRTEJcErJSQ8yNRgkZ0NrTz2qSquXiE9rp/qOE9SLBbFLvVzsMp7pRNZoTeKqNZp 1WxQ== X-Forwarded-Encrypted: i=1; AFNElJ8+2ValXjAmTh8MwTTNxYrg9Rtob5sT/hHMe7WMCT8g4sPuDWCxJc7ccMdlyAAq6sk4WkEF5lEYSL5ejYE=@vger.kernel.org X-Gm-Message-State: AOJu0YxVL9QldF2bjCjUIyKCd62u+Etiqb7XsseIqiJUytLddycHPV96 CBBlK9UlkFkFQtzAK3kBGDyi2SXFlgGHPdpJIeSthW6xXcnyN0Hd8hkk9OJ5C7aD1HU= X-Gm-Gg: Acq92OHq5hNGTTka9BbCGF7hiSllOfCsy5W4kO+cG1OVHPlrTrK3GTT8Vr4/7lSgvTz r2gMQ+dFRNerqvYQB0EBC536/Z5sf7nLsSolW93JCEJeWHT5RUKpRitOwl1vx2rg01RQNChfhTN Vtdj8mhqyRs3W+Hndh3uYKK61wmYj2EzB1mbcY7FaIb45Yn+hOeO5eXI44f/dk8JnBUV2E6LXDA U8DZfFkN4jvoS5qgyxCK81ELXwRiEyWXspDVkfp6VqrnVimoG4ROwoZtfszvQ1Y+WrahbbjewXD prCAbB1RPwPME4cGpX9A3KNiGrSkjMY/Y6OfCQ8w+v2NOGgMGnYVHDo1Xug2DtGWDlJ/i0Jemsa fS+X73vv3k54CS96ycjRQ8GmpR2hHWVo8iajQnTZ4P6VZJizL3iWZ+T8uxkRXb4he3mXj7pJ3El zzF1ag/jJu9ErpZ9rtcXNVGi+Zouwnnl4wszD4MgPl7vBChAaV X-Received: by 2002:a05:6214:80d5:10b0:8ce:b2e9:a4c2 with SMTP id 6a1803df08f44-8cecdc3c53amr52754236d6.19.1780507591707; Wed, 03 Jun 2026 10:26:31 -0700 (PDT) Received: from localhost ([161.35.96.86]) by smtp.gmail.com with UTF8SMTPSA id 6a1803df08f44-8cecd053032sm26729276d6.24.2026.06.03.10.26.31 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 03 Jun 2026 10:26:31 -0700 (PDT) From: Samuel Moelius To: Phillip Lougher Cc: Samuel Moelius , linux-kernel@vger.kernel.org (open list) Subject: [PATCH] squashfs: reject wrapped fragment index offsets Date: Wed, 3 Jun 2026 17:26:19 +0000 Message-ID: <20260603172620.23735-1-sam.moelius@trailofbits.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Squashfs fragment lookup computes byte offsets into the fragment index table from on-disk values. Crafted metadata can make that arithmetic wrap before the block is read. A corrupted image can place the fragment index offset near U64_MAX and use a non-zero length so that the end offset wraps to a low value. After the wrap, the filesystem may read the wrong metadata block instead of rejecting the corrupt image. Check fragment index offset arithmetic for overflow before issuing the read. Assisted-by: Codex:gpt-5.5-cyber-preview Signed-off-by: Samuel Moelius --- fs/squashfs/block.c | 6 ++++-- fs/squashfs/fragment.c | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index 2d5850168026..570ae6ac3652 100644 --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c @@ -312,7 +312,8 @@ int squashfs_read_data(struct super_block *sb, u64 inde= x, int length, struct bvec_iter_all iter_all =3D {}; struct bio_vec *bvec =3D bvec_init_iter_all(&iter_all); =20 - if (index + 2 > msblk->bytes_used) { + if (index > msblk->bytes_used || + msblk->bytes_used - index < 2) { res =3D -EIO; goto out; } @@ -349,7 +350,8 @@ int squashfs_read_data(struct super_block *sb, u64 inde= x, int length, compressed ? "" : "un", length); } if (length <=3D 0 || length > output->length || - (index + length) > msblk->bytes_used) { + index > msblk->bytes_used || + (u64)length > msblk->bytes_used - index) { res =3D -EIO; goto out; } diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c index 49602b9a42e1..b4a4ea83b602 100644 --- a/fs/squashfs/fragment.c +++ b/fs/squashfs/fragment.c @@ -71,7 +71,8 @@ __le64 *squashfs_read_fragment_index_table(struct super_b= lock *sb, * this check also traps instances where fragment_table_start is * incorrectly larger than the next table start */ - if (fragment_table_start + length > next_table) + if (fragment_table_start > next_table || + length > next_table - fragment_table_start) return ERR_PTR(-EINVAL); =20 table =3D squashfs_read_table(sb, fragment_table_start, length); --=20 2.43.0