From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-qv1-f53.google.com (mail-qv1-f53.google.com [209.85.219.53]) (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 F0D4D286425 for ; Wed, 15 Apr 2026 12:48:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.53 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776257315; cv=none; b=KziovaJGpJs16aEVQEAVvRfibuch8lle7CwTnMHx7RyQm21cYsLB6HiCo2eDoC3oQXoznT7r2UIB4QYN0dbxlmd1YwfYuiPNiE8cSvg1/gij+2ifEB7fRRGUunFowrzAhQBeol8INsHQglMIJ9vBfb6xVjqSjUk3B30Wcb5ho7c= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776257315; c=relaxed/simple; bh=O8/U/H7RuBMpTrEG9U+Ek+bErzkINikrqOQBMJ11wfU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=E+cxOgFgFKryNw1vLlx0fJ0PDBV7KvJBoG4zZTzCvk9bCX469iEsi98KF2Zs/1Ck7XxKzieWQ/sZdv5EEZj+Ke6MO8YyvE5FN6Nk9MhD7qTiR1JFi1xqUS/H6LFAt3dDhwiPFGmDdAHOfGXYJhKmMZcch5u/ytQMIV5Pj7FO320= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=NLJqmM7N; arc=none smtp.client-ip=209.85.219.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="NLJqmM7N" Received: by mail-qv1-f53.google.com with SMTP id 6a1803df08f44-8a068db9989so63836046d6.0 for ; Wed, 15 Apr 2026 05:48:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776257309; x=1776862109; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=9LmrK3+P1rULpl1i+7wOpfSUhGy0lxg+p+4MR2uQ/+M=; b=NLJqmM7Ndmoa9jFFEybupk2Ph9cdRhBCRD8HpWG7eQAuX0TbKcDhqT5Ipn2Zdv0rE0 /GipTarduc+3wuOVwcDY31a8fT23GNNVUBEIG+P1SH9nqWDoQrneleOb/Sfomom/xk4t PQXJS0FTT27GxVhGQy1NqT3v151T1jLYLCB3hR4xgBNJyCimxCBDJoqnhGmmIIWCopB1 crphDrlOw0D6r0DFWauk3uNhPLFGEYk3llKAji8v+28BfcghL/Gf6+Hsy+nAIcnpDmF6 16FD3WBWxSK1Uy+Ql+wgzH+E3xzNAzIbAiZiVm8dk02BU8mnvb6uKgTzs35QZ5xl57LN SuFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776257309; x=1776862109; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=9LmrK3+P1rULpl1i+7wOpfSUhGy0lxg+p+4MR2uQ/+M=; b=jcRp/fL1MZtve5AD8KtBieWIgkWSpPqddwXEwG2gbHgtsq3y9CUYZWFtG4zptmOfMf zLyPDllebdY3G5ckMD1a5VMBleEASMPP/XQyBxTfNG17p4RVNkgMCDH1z6WobP5svjUx cTH0LaYSsSf9cDyyA3ySNsS05bb1i/F5CiORDeM07AtrHs70LB0tQX9qbW5/7pGEstZM 9AsdtkwcGdy5Lp8gZyHK5PJQSUq+WCEvv02m7bcJxPMfE3hIDOuustC3HUgmP4EWcsLV 99xCQ/f2Z4AYp9X2D4AMHyOyzur5BVXR0eTlRix3ngxeavUiXB2M4Vefn51IZ9Z+gKL6 XW+w== X-Forwarded-Encrypted: i=1; AFNElJ87oB0MLlpvoBUAB+9+/ll175NZRGBiOXJhpSWJCurRpuve+nUqc+zEZaN1ivoYaFXQFr3q4LN+EA9XM+U=@vger.kernel.org X-Gm-Message-State: AOJu0Yz7wTJyySFrhNfse/mIwsckVX4rFzhHk6QoiRTUJr6XoLQe4inZ fASjYmHI5niNPMj7wD1JP+MxC5xtn6558zN+lTcxNnlQilJpv1dn6nRS X-Gm-Gg: AeBDiet7px2X0dJrmSwQ9w5JkpkzlpO7Iv3qsoMDR16bFpG5NL+ImbAszvbHgJekEcz Jlf3Xw3TBIsB9dvrzGjJi6AwInZ+orMLXBDANVXDRoLpTAN+LgQaPetjRwTWvfBId8zDSB4/tdv b9eDrIYxSgZ2l3z9MtYuKuIXpZD0PDOE1G/VNAm1iUqxXyB09C9iCkP/6jK6u93eo6748RaMTqx gtrQLrquyu9AQwB1UrTCm2tCBpPxglwAzGjd5q/uaPZFjubYawOWm9Ytpu88+FAybwsy9aupsyl zYNzGZmum0RMIwEvsvTwMfHlVTe4hs2/17SzzJlyaz8LYao0//+FpDBC3/ldSDHxfRuOeMsHQ2A iQaegFXBxQjkzdY5Epv0sMdtQ1YDC9M4JDldCfvttpk4Xs/kD3yjHwdK7ArXYRZvOz/bF1I2hcl gGQaYJ/vhZbd6nWFcCNkN/vtHrRHqah+xxBbNsIDHiiqat6LZgVKGv4u4q07fnTgxy3/IUG7aT/ JLY+BbLxU+2ik3DyssDuJIyvohX6TqpmhWo9fvcc+ZD3/BXfu760A== X-Received: by 2002:a05:6214:765:b0:89c:637a:6bb with SMTP id 6a1803df08f44-8ac860e6200mr326656306d6.4.1776257309176; Wed, 15 Apr 2026 05:48:29 -0700 (PDT) Received: from server0.tail6e7dd.ts.net (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-8ae6ceb891csm10614016d6.48.2026.04.15.05.48.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Apr 2026 05:48:28 -0700 (PDT) From: Michael Bommarito To: linux-mtd@lists.infradead.org, David Woodhouse , Richard Weinberger Cc: Zhihao Cheng , Artem Sadovnikov , Kees Cook , linux-kernel@vger.kernel.org Subject: [PATCH 1/2] jffs2: reject truncated summary node before header validation Date: Wed, 15 Apr 2026 08:48:12 -0400 Message-ID: <20260415124813.246588-2-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260415124813.246588-1-michael.bommarito@gmail.com> References: <20260415124813.246588-1-michael.bommarito@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit jffs2_sum_scan_sumnode() is called from jffs2_scan_eraseblock() with sumsize derived from the on-flash jffs2_sum_marker::offset: sumlen = c->sector_size - je32_to_cpu(sm->offset); A crafted flash image can set sm->offset so that sumsize < JFFS2_SUMMARY_FRAME_SIZE (= sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker) = 40, the minimum frame the writer at jffs2_sum_write_sumnode() emits and the minimum sumlen that corresponds to a legitimate on-flash layout). The function then reads the summary header unchecked: crcnode.totlen = summary->totlen; /* offset +4 */ crc = crc32(0, &crcnode, sizeof(crcnode)-4); if (je32_to_cpu(summary->hdr_crc) != crc) /* offset +8 */ goto crc_err; if (je32_to_cpu(summary->totlen) != sumsize) goto crc_err; crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8); if (je32_to_cpu(summary->node_crc) != crc) /* offset +28 */ goto crc_err; crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary)); Each header read at offset +4, +8 and +28 of a too-small buffer is a slab out-of-bounds read. Worse, sumsize - sizeof(struct jffs2_raw_summary) underflows in size_t and the final crc32() walks ~16 EiB of memory, which translates to a kernel oops on mount once the walk hits unmapped memory. Reachable whenever a crafted JFFS2 flash image is mounted: typical in embedded systems where flash can be rewritten out-of-band (JTAG, SPI flasher, hostile firmware update) and the device auto-mounts JFFS2 on boot, or any CAP_SYS_ADMIN context that supplies the MTD backing. Bounding on JFFS2_SUMMARY_FRAME_SIZE matches the actual on-flash frame layout the writer emits and does not reject any legitimate image. Reproduced on v7.0-rc7 under UML + CONFIG_KASAN=y with a 16 MiB block2mtd-backed image whose first erase block's jffs2_sum_marker points at sector_size; pre-fix: BUG: KASAN: slab-out-of-bounds in jffs2_sum_scan_sumnode+0x131/0x1611 Read of size 4 at addr 00000000621fb004 by task mount/31 Allocated by mtd_kmalloc_up_to via jffs2_scan_medium+0x246 Located 4 bytes to the right of allocated 4096-byte region Post-fix the same image is rejected cleanly with a warning and mount falls back to the full scan path. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Michael Bommarito --- fs/jffs2/summary.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 4521a7723f30..150a9c83cb05 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -577,6 +577,15 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb int ret, ofs; uint32_t crc; + /* Reject frames that can't hold the header + marker the writer + * always emits (also blocks the sumsize - sizeof(*summary) + * size_t underflow at the sum_crc check below). */ + if (sumsize < JFFS2_SUMMARY_FRAME_SIZE) { + JFFS2_WARNING("Summary node too small (%u bytes), skipping.\n", + sumsize); + return 0; + } + ofs = c->sector_size - sumsize; dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", -- 2.53.0