From nobody Tue Jun 16 02:35:14 2026 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: quoted-printable Content-Type: text/plain; charset="utf-8" jffs2_sum_scan_sumnode() is called from jffs2_scan_eraseblock() with sumsize derived from the on-flash jffs2_sum_marker::offset: sumlen =3D c->sector_size - je32_to_cpu(sm->offset); A crafted flash image can set sm->offset so that sumsize < JFFS2_SUMMARY_FRAME_SIZE (=3D sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker) =3D 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 =3D summary->totlen; /* offset +4 */ crc =3D crc32(0, &crcnode, sizeof(crcnode)-4); if (je32_to_cpu(summary->hdr_crc) !=3D crc) /* offset +8 */ goto crc_err; if (je32_to_cpu(summary->totlen) !=3D sumsize) goto crc_err; crc =3D crc32(0, summary, sizeof(struct jffs2_raw_summary)-8); if (je32_to_cpu(summary->node_crc) !=3D crc) /* offset +28 */ goto crc_err; crc =3D 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=3Dy 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, st= ruct jffs2_eraseblock *jeb int ret, ofs; uint32_t crc; =20 + /* 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 =3D c->sector_size - sumsize; =20 dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", --=20 2.53.0 From nobody Tue Jun 16 02:35:14 2026 Received: from mail-qk1-f172.google.com (mail-qk1-f172.google.com [209.85.222.172]) (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 5BD984A07 for ; Wed, 15 Apr 2026 12:48:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776257316; cv=none; b=jyYws/11n912TGwdlek8o/FyYX98MNwckAcLcQTECkWd6gOPk2eslmU0K30LabmKjUtnH5EicCdGZ6QAq5qspPUMKU4qWjEY4ggxnYyhG0ab2v5s96jcdXNcM33sfXLpepKD3i53sfvPQnmDKbubgw4E1BLCXaXdb4P7kXiebH4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776257316; c=relaxed/simple; bh=cfV+tXFX3fbRcKkidMaCzHWx7xRYreVRzrk/zy3ZYEk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SLq5e7fYHIebIeFOfLiFl59KP2Axq8b0zgknD0bbt1Uuc+8wTRANak/agAVw4tg3EyggSqPWu63dOY06ZecbHmJep80WhpmPXAj+nGWMFX78nz7BDq7nKwD10t0mVuCtk6jxzHAfyfHffFjWDrrDrEWgsMlC6hFLd0oJsOTZ/C0= 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=r4ri8vwE; arc=none smtp.client-ip=209.85.222.172 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="r4ri8vwE" Received: by mail-qk1-f172.google.com with SMTP id af79cd13be357-8d7e7f48499so657824685a.1 for ; Wed, 15 Apr 2026 05:48:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1776257310; x=1776862110; 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=kjxJXStMU5U0NlRTJ2IsoioP7S3PUNh6UBqJINw6hTA=; b=r4ri8vwEymcOJwmpiR8F/al4Idc4y+8EcPIdm2WLI/RtTGGOUSLufgj6ciJ8ATUSja LGBaCHHavEEpqSLDMEuO+BZHwrpiHXeZLLQcMAZvXkp8jbk/VPCMYUtdQ8LL/WTluDYm Yyz4Jm0ID419SGZysy6PdgO+t8Rjozb8RRzj4tVPD3S4vjZQCyIbFMruKYByAOKyNM/j hGoSDSLUcMPPUtuYZ3gqbTNUIJIUNJrP4aWBRjdUYLHnUWAydM6nx5p5QCWwx9eAyDLL pTk6DX0I/+ObWSdYtJgZWJqXibwGBvZNFIZvN45zVtIX/7c7cXT3XsuLXH3LGexAs5t7 AqAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1776257310; x=1776862110; 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=kjxJXStMU5U0NlRTJ2IsoioP7S3PUNh6UBqJINw6hTA=; b=iC21SLkZvesTa9PNFK1983dpiZbcbOFCrnitwuNSEV6q1D+ppN03qF0U8FiUWolCrl PXgdY2zAsTiFPsOfyoJOT4Y1XV1hTid8twuxP8vbmgjDPMrWo4i3nsU0uWt8t0oQg1de TTE/zCjoLP/vtg8ixWqwH/SXgonRsWo4MZ+pRSwyi5A3TjBbG2EcqpYtFSyGjtOTNcC+ Kq63Wfm5Jxwvy9TjwqvxKRCUJCBdux48y00sBi+wTR5Uyt9HHg7nn06U5PzloxrHZSFW ZVl4Auc7HRoBHNICGmqS9LoI+AfspFcOixEBPE3f4oA4IqK3uIHNPYUOxYKW6SPMe+Yc j7Ig== X-Forwarded-Encrypted: i=1; AFNElJ+++YXLHV2ZSQe+PfdAvlzoxB5y3yb5SkxH1cwrDZ6sJgGkssqcmaVnjpgv92JBeaKls9ooNqRIjyUPJ8s=@vger.kernel.org X-Gm-Message-State: AOJu0Yy7jwmDx2Le03cIAwyc0d5hfvhT4Ps6orG2cjMaZTSUQ8BTY1lu 4e20cvoB+SJtK1olH6Dqf5RuZHJgteWcoptG967Rpha/eHf61SQ9TsEl5HLT4A== X-Gm-Gg: AeBDiev6q6PQejLjcvQJwLGlXXIXBnoWBw/VeidkcZyZVXJlgQMAb/HlbCBHW6xcyYz Y6dVZ6faReof7dRadBOWCddd+eCaHhxmooUB8v1N0Z7mmJOf1uy4dgd/ZuHcmNvmp8Jw6/bfRrg ram3FCYCh/tMjBAwW303mZvvUE7qCNzz1/iCOqneb1u2QNzu68W5EQK647lxPnSiY82hY7lmHS6 21NsuJJQtgmZxr7Tenom4DeplCf7p1qC3sR5BKQtWlwWaUVRoRl++Bzj5NjqPJzO5Kl1ipxVxkD p/6WIqoOC0YRXC0sgcc4Mj/ysveXbLDGzCYBA+ggb5ps78vMTTZ97p5+e1a3TJeclbODxHkMVFn g2IcX+FGPqYTo3dWobfjulu3emtfti9BvE/1DEDcf+YAcgLpKFEh4WXat/sueRfiVj9zZf3pfh9 imWszwkiURa3dzNdSe9kwsSZO6/wWxxZRFWfGLVVka9AnNNJ2SqVx1HdHg8tJpIHyGYN6i4LpoO dQJLDEVYe17DIXNOojwDS1UypIVcCMVBEek5ZauQDA8lvcUy0s4xQ== X-Received: by 2002:a05:620a:450b:b0:8cd:b620:f3ed with SMTP id af79cd13be357-8ddcf2bf6e4mr3124006385a.38.1776257310347; Wed, 15 Apr 2026 05:48:30 -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.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Apr 2026 05:48:29 -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 2/2] jffs2: bound summary entry walks against the payload Date: Wed, 15 Apr 2026 08:48:13 -0400 Message-ID: <20260415124813.246588-3-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: quoted-printable Content-Type: text/plain; charset="utf-8" jffs2_sum_process_sum_data() iterates summary->sum_num times, reading the next entry's nodetype from the current sp and dispatching into type-specific handlers that advance sp by a fixed or nsize-dependent amount. There is no upper bound on sum_num from the writer side, and on read the scanner trusts the on-flash value unchecked. A crafted flash image can therefore set sum_num > (actual entries that fit in the payload). Once sp runs off the end of the summary buffer the nodetype read at summary.c:407 lands on adjacent slab memory. If those bytes happen to decode as one of the known types (JFFS2_NODETYPE_INODE / _DIRENT / _XATTR / _XREF) the handler calls sum_link_node_ref() with offset / totlen pulled from whatever slab neighbor is next to the scan buffer. Reproduced on v7.0-rc7 under UML + CONFIG_KASAN=3Dy with a crafted image carrying one real INODE entry and sum_num=3D2: BUG: KASAN: slab-out-of-bounds in jffs2_sum_scan_sumnode+0x6bd Read of size 2 at addr 00000000621fb000 by task mount/31 Located 0 bytes to the right of allocated 4096-byte region The matching sum_num=3D1 image (same bytes, honest sum_num) mounts without a KASAN report, so the OOB is sum_num-specific. Pass sumsize into jffs2_sum_process_sum_data() and bound sp against summary + sumsize - sizeof(struct jffs2_sum_marker) before every nodetype read and before every type-specific field access. If the advance would leave the payload, warn and fall back to a full scan via -ENOTRECOVERABLE. Scope note on impact: demonstrated effect is a mount-time OOB read and a default-case warning path that reclaims the jeb. The type-specific handlers run with attacker-influenced offset/totlen pulled from the OOB bytes and do call sum_link_node_ref(), but persistent write/state-corruption requires adjacent slab content to decode as a known nodetype and the mount to complete cleanly; neither is reliably reproducible without heap-spray primitives. This patch closes the confirmed OOB-read sites. Assisted-by: Claude:claude-opus-4-6 Signed-off-by: Michael Bommarito --- fs/jffs2/summary.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 150a9c83cb05..09677b931010 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -384,21 +384,33 @@ static struct jffs2_raw_node_ref *sum_link_node_ref(s= truct jffs2_sb_info *c, /* Process the stored summary information - helper function for jffs2_sum_= scan_sumnode() */ =20 static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs= 2_eraseblock *jeb, - struct jffs2_raw_summary *summary, uint32_t *pseudo_random) + struct jffs2_raw_summary *summary, uint32_t sumsize, + uint32_t *pseudo_random) { struct jffs2_inode_cache *ic; struct jffs2_full_dirent *fd; - void *sp; + void *sp, *sum_end; int i, ino; int err; =20 sp =3D summary->sum; + /* Entries must fit before the trailing jffs2_sum_marker. */ + sum_end =3D (char *)summary + sumsize - sizeof(struct jffs2_sum_marker); =20 for (i=3D0; isum_num); i++) { dbg_summary("processing summary index %d\n", i); =20 cond_resched(); =20 + /* Make sure the nodetype dispatched on is in-bounds; each + * case re-checks the specific entry size before advancing + * sp past the node's fields. */ + if ((char *)sp + sizeof(struct jffs2_sum_unknown_flash) > (char *)sum_en= d) { + JFFS2_WARNING("Summary entry %d nodetype past payload (sum_num=3D%u)\n", + i, je32_to_cpu(summary->sum_num)); + return -ENOTRECOVERABLE; + } + /* Make sure there's a spare ref for dirty space */ err =3D jffs2_prealloc_raw_node_refs(c, jeb, 2); if (err) @@ -407,6 +419,9 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_i= nfo *c, struct jffs2_eras switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { case JFFS2_NODETYPE_INODE: { struct jffs2_sum_inode_flash *spi; + + if ((char *)sp + JFFS2_SUMMARY_INODE_SIZE > (char *)sum_end) + goto ent_past_end; spi =3D sp; =20 ino =3D je32_to_cpu(spi->inode); @@ -434,7 +449,12 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_= info *c, struct jffs2_eras case JFFS2_NODETYPE_DIRENT: { struct jffs2_sum_dirent_flash *spd; int checkedlen; + + if ((char *)sp + sizeof(*spd) > (char *)sum_end) + goto ent_past_end; spd =3D sp; + if ((char *)sp + JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize) > (char *)sum_e= nd) + goto ent_past_end; =20 dbg_summary("Dirent at 0x%08x-0x%08x\n", jeb->offset + je32_to_cpu(spd->offset), @@ -492,6 +512,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_i= nfo *c, struct jffs2_eras struct jffs2_xattr_datum *xd; struct jffs2_sum_xattr_flash *spx; =20 + if ((char *)sp + JFFS2_SUMMARY_XATTR_SIZE > (char *)sum_end) + goto ent_past_end; spx =3D (struct jffs2_sum_xattr_flash *)sp; dbg_summary("xattr at %#08x-%#08x (xid=3D%u, version=3D%u)\n",=20 jeb->offset + je32_to_cpu(spx->offset), @@ -523,6 +545,8 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_i= nfo *c, struct jffs2_eras struct jffs2_xattr_ref *ref; struct jffs2_sum_xref_flash *spr; =20 + if ((char *)sp + JFFS2_SUMMARY_XREF_SIZE > (char *)sum_end) + goto ent_past_end; spr =3D (struct jffs2_sum_xref_flash *)sp; dbg_summary("xref at %#08x-%#08x\n", jeb->offset + je32_to_cpu(spr->offset), @@ -566,6 +590,11 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_= info *c, struct jffs2_eras } } return 0; + +ent_past_end: + JFFS2_WARNING("Summary entry %d past payload end (sum_num=3D%u)\n", + i, je32_to_cpu(summary->sum_num)); + return -ENOTRECOVERABLE; } =20 /* Process the summary node - called from jffs2_scan_eraseblock() */ @@ -646,7 +675,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, str= uct jffs2_eraseblock *jeb } } =20 - ret =3D jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); + ret =3D jffs2_sum_process_sum_data(c, jeb, summary, sumsize, pseudo_rando= m); /* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full scan of this eraseblock. So return zero */ if (ret =3D=3D -ENOTRECOVERABLE) --=20 2.53.0