From nobody Mon Jun 8 22:54:50 2026 Received: from mail-pj1-f51.google.com (mail-pj1-f51.google.com [209.85.216.51]) (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 54DE5288C2D for ; Tue, 26 May 2026 05:36:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779773769; cv=none; b=nFWl+64TZmL2nmzFLBEYZxx9XWFgt1cF1v2x4/80c3AFP9FEeVpiQMyVPSfiPi2CWyeUiTXSodOJ3uMaYAwYQcJY1wTVM/Yj406QWX01ZLSMjUWZOA7kjHftfuLt6OOwtIzH/q+Tyq2QAurJR5tOiadeT7DPEuvykOeYAs5lztU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779773769; c=relaxed/simple; bh=ty9GZrdaPGqa8+2DchyL64zybj66afmOgdIH2kafWcA=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=XJp4I2ryYH2nUwh2hrsz78Og+Eb8mUpbg4+g4b/dkEZrjEkbQt/9sX5gx9q5NEfDQN1w+H2OdilgIUGfEokhUU/UuDT64MZhyI7qU8fUAHMv7n4rDmUI0BzGWRW7JO/pGAj7JXxBUAPWJN+5N7+j9hDIovC/NuyLZiUJJba7GUg= 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=b1aZvUBO; arc=none smtp.client-ip=209.85.216.51 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="b1aZvUBO" Received: by mail-pj1-f51.google.com with SMTP id 98e67ed59e1d1-3698e34a567so9421872a91.2 for ; Mon, 25 May 2026 22:36:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779773768; x=1780378568; 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=L8sMiHhDi5X06YZ5Z6Hrq+UhNSJVExmPOyUWtvQndg4=; b=b1aZvUBOU0oMlt/5Dt51UpP7+9BYZpZ/v8ZdhrUVqBxVCZ5CJXcvDBx1PLX5BAx+fw EArY2C0HcaJ6tuPP6aFJPQe9+IuNvCaSxkeIl7nTPqS3Rgzs73JzrIIQwlXoJE0qF5xq yvzZMiFQSpYnQT7k+5jnVrmx2OueTPL1nJPzTcLy3gErNc34iGWDdo/QWMbeU2atLaE3 u9ohCAcXV7OkekF6i9kXwOrNEr7Dwf0IH68N8NtmjQj3qDVyP+PNaqTZyJGDPaAp/Nt+ IBsIwujf275iyhmIrQUG7IVaXB6pg3D3pu7VM1wD0+ekBgtdCJteMpgcyN+pmTpBR5lY i9mA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779773768; x=1780378568; 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=L8sMiHhDi5X06YZ5Z6Hrq+UhNSJVExmPOyUWtvQndg4=; b=KpTph4h5BjMV3yEycFfZRGdbe8vM6gKKwBiALdNBKHxcC7vq61prwCn6royEnI1ENJ ewVH8ctRpdx/3HSB6v6ELwKHwFjcBLnPofYd22FfriFwDVyjMNpNqRMTJAaPKUfvy04U q9zjSdMb6q5K5behudiKK+8+Vi4e2DYrG8n2YW33s7HDJ3hnzwlJCJC/MORNT+DyCsPg ZU49Jlz3F0dRfT+96JooA04eqF0jgiX2ITS0JiGxtttyk5ip51TH2KaEXqrplRQ1bkU7 bzoZxiNXDJfRRu4X+ncutmC9fWJSWF8Gcazew5d+I3hcs1fGP5aQ18k6eA7AuNGTbaUy qzxg== X-Forwarded-Encrypted: i=1; AFNElJ+ztPaVqrCblzz+Vt78dv7zMklYa1bn+g/zwGEJkkq4BzJxpIaSb7Iq7czMfvbtSr2kghf0qPsM1K7BWaE=@vger.kernel.org X-Gm-Message-State: AOJu0YwND/sp92GzQ2ayKINXKT8T+jHSFzuKUVVwFdpJYf8Eb5jvd4UB SCq6iNGywNU0F3TjJl9s/eV/c5EPiRnR7kUWObTUArzssZjkjfKghaa8 X-Gm-Gg: Acq92OFdQJTYr6X6eH9e/7t8cBhMah4uyP9pJXFyBnlh0XHXbsSEguiErFN6RKodmA/ X652CKDWMByerNgWIV0PkO+1s2ZapVCSBdqpNYuYHtfXvheXe2zcTjAlUe2X2FeKv+j9Q063TYe pjjmUiLmkDqfpWlOIVDzZVTj+TFuSEhm9gmRcqyhF72VXV5LEWWgEPalFmx9zNt1VGz00zUOy3R uh8nW+oL8vJfh4uCFdHTyVcZeRKpWV3Ri1K9oaevau9vm8lvvUR4POFmxExzRo8TYXaApDC3yAJ rjD9n4ItLxZ24WW8YvgLJ8kw0XDaySk+cyPeKAkQWT987cvWw4Td6TCpkSiJmQl8frcoILV+4PL IdqsgSrmSNE9NPdDe8CmwAvRcowKZMy6anIjidFN7KP9raUkXLrxL8XYVQi7YONOmsVqN+dCRX9 R0ve9vKgx8hwkTDAtWBYNcFidJ+gZQdg3gttQ0SgVUcdNyvB0ZholqvtyP8dq8og/3ZUZEWA== X-Received: by 2002:a17:90b:48c1:b0:35f:c729:de9b with SMTP id 98e67ed59e1d1-36a677f44b2mr18075721a91.20.1779773767539; Mon, 25 May 2026 22:36:07 -0700 (PDT) Received: from qiwenjie-ThinkCentre-M760t.mioffice.cn ([43.224.245.241]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-36afbc766d2sm1797252a91.14.2026.05.25.22.36.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 May 2026 22:36:07 -0700 (PDT) From: Wenjie Qi X-Google-Original-From: Wenjie Qi To: jaegeuk@kernel.org, chao@kernel.org Cc: chur.lee@samsung.com, linux-f2fs-devel@lists.sourceforge.net, linux-kernel@vger.kernel.org, stable@kernel.org, qiwenjie@xiaomi.com, qwjhust@gmail.com Subject: [PATCH v2] f2fs: validate orphan inode entry count Date: Tue, 26 May 2026 13:35:57 +0800 Message-ID: <20260526053557.1096229-1-qiwenjie@xiaomi.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" f2fs_recover_orphan_inodes() trusts the orphan block entry_count when replaying orphan inodes from the checkpoint pack. A corrupted entry_count larger than F2FS_ORPHANS_PER_BLOCK makes the recovery loop read past the ino[] array and interpret footer or following data as inode numbers. On a crafted image, mounting an unpatched kernel can drive orphan recovery into f2fs_bug_on() and panic the kernel. Validate entry_count before consuming entries so corrupted checkpoint data fails the mount with -EFSCORRUPTED and requests fsck instead. Set ERROR_INCONSISTENT_ORPHAN as well, so the corruption reason can be recorded in the superblock s_errors[] field. This gives fsck a persistent hint even though mount-time orphan recovery failure may leave no chance to persist SBI_NEED_FSCK through a checkpoint. Fixes: 127e670abfa7 ("f2fs: add checkpoint operations") Cc: stable@kernel.org Signed-off-by: Wenjie Qi --- Changes in v2: - Add ERROR_INCONSISTENT_ORPHAN to persist an orphan metadata corruption hint in s_errors[]. - Call f2fs_handle_error() when orphan entry_count is invalid. fs/f2fs/checkpoint.c | 14 +++++++++++++- include/linux/f2fs_fs.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index c00a6b6ebcbd..064f5b537423 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -943,6 +943,7 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi) for (i =3D 0; i < orphan_blocks; i++) { struct folio *folio; struct f2fs_orphan_block *orphan_blk; + unsigned int entry_count; =20 folio =3D f2fs_get_meta_folio(sbi, start_blk + i); if (IS_ERR(folio)) { @@ -951,7 +952,18 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sb= i) } =20 orphan_blk =3D folio_address(folio); - for (j =3D 0; j < le32_to_cpu(orphan_blk->entry_count); j++) { + entry_count =3D le32_to_cpu(orphan_blk->entry_count); + if (entry_count > F2FS_ORPHANS_PER_BLOCK) { + f2fs_err(sbi, "invalid orphan inode entry count %u", + entry_count); + set_sbi_flag(sbi, SBI_NEED_FSCK); + f2fs_handle_error(sbi, ERROR_INCONSISTENT_ORPHAN); + err =3D -EFSCORRUPTED; + f2fs_folio_put(folio, true); + goto out; + } + + for (j =3D 0; j < entry_count; j++) { nid_t ino =3D le32_to_cpu(orphan_blk->ino[j]); =20 err =3D recover_orphan_inode(sbi, ino); diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h index 829a59399dac..bb2b6cd5d507 100644 --- a/include/linux/f2fs_fs.h +++ b/include/linux/f2fs_fs.h @@ -107,6 +107,7 @@ enum f2fs_error { ERROR_CORRUPTED_XATTR, ERROR_INVALID_NODE_REFERENCE, ERROR_INCONSISTENT_NAT, + ERROR_INCONSISTENT_ORPHAN, ERROR_MAX, }; =20 --=20 2.43.0