The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH v2 0/3] ocfs2: harden inode validators against forged metadata
@ 2026-05-19 11:04 Michael Bommarito
  2026-05-19 11:04 ` [PATCH v2 1/3] ocfs2: reject dinodes with non-canonical i_mode type Michael Bommarito
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Michael Bommarito @ 2026-05-19 11:04 UTC (permalink / raw)
  To: Joseph Qi, Mark Fasheh, Joel Becker
  Cc: ZhengYuan Huang, ocfs2-devel, linux-fsdevel, linux-kernel

This series adds three structural checks to OCFS2 dinode validation so
malformed on-disk fields are rejected before ocfs2_populate_inode()
copies them into the in-core inode.

The checks cover:

  - i_mode values whose type bits do not name a canonical POSIX file
    type;
  - non-device dinodes whose id1.dev1.i_rdev field is non-zero; and
  - non-inline dinodes that claim non-zero i_size while i_clusters is
    zero, covering directories unconditionally and regular files on
    non-sparse volumes.

The normal read path reports these through ocfs2_error(), matching the
existing suballoc-slot, inline-data, chain-list, and refcount checks.
The online filecheck path uses the same structural predicates but keeps
its own reporting contract, returning OCFS2_FILECHECK_ERR_INVALIDINO
instead of calling ocfs2_error().

Validation from v1 still applies to the unchanged reachability model.

---

Changes in v2:

  - Patch 1 drops the tautological S_IFMT|07777 mask check and reuses
    fs_umode_to_ftype() for the canonical file-type predicate.
  - Patch 1 mirrors the i_mode check in the online filecheck path.
  - Patch 2 factors the i_rdev cross-check into a shared predicate.
  - Patch 2 mirrors the i_rdev check in the online filecheck path.
  - Patch 3 factors the size/cluster invariant into a shared predicate.
  - Patch 3 extends the zero-cluster rejection to non-inline
    directories, while preserving the sparse regular-file carveout.
  - Patch 3 mirrors the size/cluster check in the online filecheck path.
  - Patches 1 and 3 add Link trailers to the Sashiko review Andrew
    pointed out.

Testing after v2:

  - Replayed all three patches onto the original base, checked with
    checkpatch --strict, and applied cleanly with git am.
  - Rebuilt a fresh bzImage from the v2-applied tree.
  - Booted that v2 kernel five times under QEMU: sparse regular-file
    regression, non-sparse no-forge regression, forged non-canonical
    i_mode, forged non-device i_rdev, and forged non-zero i_size with
    zero i_clusters.
  - The three forged dinodes were rejected by
    ocfs2_validate_inode_block(); the two unforged regression cases
    completed without validator errors.

Michael Bommarito (3):
  ocfs2: reject dinodes with non-canonical i_mode type
  ocfs2: reject dinodes whose i_rdev disagrees with the file type
  ocfs2: reject non-inline dinodes with i_size and zero i_clusters

 fs/ocfs2/inode.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 149 insertions(+), 2 deletions(-)

-- 
2.53.0

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2 1/3] ocfs2: reject dinodes with non-canonical i_mode type
  2026-05-19 11:04 [PATCH v2 0/3] ocfs2: harden inode validators against forged metadata Michael Bommarito
@ 2026-05-19 11:04 ` Michael Bommarito
  2026-05-19 12:21   ` Joseph Qi
  2026-06-01 18:19   ` Joel Becker
  2026-05-19 11:04 ` [PATCH v2 2/3] ocfs2: reject dinodes whose i_rdev disagrees with the file type Michael Bommarito
  2026-05-19 11:04 ` [PATCH v2 3/3] ocfs2: reject non-inline dinodes with i_size and zero i_clusters Michael Bommarito
  2 siblings, 2 replies; 9+ messages in thread
From: Michael Bommarito @ 2026-05-19 11:04 UTC (permalink / raw)
  To: Joseph Qi, Mark Fasheh, Joel Becker
  Cc: ZhengYuan Huang, ocfs2-devel, linux-fsdevel, linux-kernel

ocfs2_validate_inode_block() currently accepts any non-zero i_mode value.
ocfs2_populate_inode() then copies that mode verbatim into inode->i_mode
and dispatches on i_mode & S_IFMT to the file/dir/symlink/special_file
iops; an unrecognised type falls through to ocfs2_special_file_iops and
init_special_inode().

Reject dinodes whose type bits do not name one of the seven canonical
POSIX file types.  Use fs_umode_to_ftype(), the same generic file-type
conversion helper OCFS2 already uses for directory entries, so the
accepted inode type set matches the kernel file-type vocabulary instead
of open-coding a local switch.

Apply the same structural check to the online filecheck read path.
filecheck keeps its own error namespace, so it reports malformed i_mode
through the filecheck logger and OCFS2_FILECHECK_ERR_INVALIDINO instead
of calling ocfs2_error(), but it must not allow a malformed dinode to
proceed into ocfs2_populate_inode().

Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.")
Cc: stable@vger.kernel.org
Link: https://sashiko.dev/#/patchset/20260517111015.3187935-1-michael.bommarito%40gmail.com
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Assisted-by: Claude:claude-opus-4-7
---
 fs/ocfs2/inode.c | 36 ++++++++++++++++++++++++++++++++++--
 1 file changed, 34 insertions(+), 2 deletions(-)

diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index a510a0eb1adcc..e149ccbdc03ce 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -13,6 +13,7 @@
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
 #include <linux/iversion.h>
+#include <linux/fs_dirent.h>
 
 #include <asm/byteorder.h>
 
@@ -64,7 +65,12 @@ static int ocfs2_filecheck_read_inode_block_full(struct inode *inode,
 static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
 						struct buffer_head *bh);
 static int ocfs2_filecheck_repair_inode_block(struct super_block *sb,
-					      struct buffer_head *bh);
+						      struct buffer_head *bh);
+
+static bool ocfs2_valid_inode_mode(umode_t mode)
+{
+	return fs_umode_to_ftype(mode) != FT_UNKNOWN;
+}
 
 void ocfs2_set_inode_flags(struct inode *inode)
 {
@@ -1494,6 +1500,24 @@ int ocfs2_validate_inode_block(struct super_block *sb,
 		goto bail;
 	}
 
+	/*
+	 * Reject dinodes whose i_mode does not name one of the seven
+	 * canonical POSIX file types.  ocfs2_populate_inode() copies
+	 * i_mode verbatim into inode->i_mode and then dispatches via
+	 * switch (mode & S_IFMT) to file/dir/symlink/special_file iops;
+	 * an unrecognised type falls into ocfs2_special_file_iops with
+	 * init_special_inode(), which interprets i_rdev.  Constrain the
+	 * type here so the dispatch only ever sees a value mkfs.ocfs2 /
+	 * VFS can produce.
+	 */
+	if (!ocfs2_valid_inode_mode(le16_to_cpu(di->i_mode))) {
+		rc = ocfs2_error(sb,
+				 "Invalid dinode #%llu: mode 0%o has unknown file type\n",
+				 (unsigned long long)bh->b_blocknr,
+				 le16_to_cpu(di->i_mode));
+		goto bail;
+	}
+
 	if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) {
 		struct ocfs2_inline_data *data = &di->id2.i_data;
 
@@ -1624,6 +1648,15 @@ static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
 		     (unsigned long long)bh->b_blocknr,
 		     le32_to_cpu(di->i_fs_generation));
 		rc = -OCFS2_FILECHECK_ERR_GENERATION;
+		goto bail;
+	}
+
+	if (!ocfs2_valid_inode_mode(le16_to_cpu(di->i_mode))) {
+		mlog(ML_ERROR,
+		     "Filecheck: invalid dinode #%llu: mode 0%o has unknown file type\n",
+		     (unsigned long long)bh->b_blocknr,
+		     le16_to_cpu(di->i_mode));
+		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
 	}
 
 bail:
@@ -1812,4 +1845,3 @@ const struct ocfs2_caching_operations ocfs2_inode_caching_ops = {
 	.co_io_lock		= ocfs2_inode_cache_io_lock,
 	.co_io_unlock		= ocfs2_inode_cache_io_unlock,
 };
-
-- 
2.53.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/3] ocfs2: reject dinodes whose i_rdev disagrees with the file type
  2026-05-19 11:04 [PATCH v2 0/3] ocfs2: harden inode validators against forged metadata Michael Bommarito
  2026-05-19 11:04 ` [PATCH v2 1/3] ocfs2: reject dinodes with non-canonical i_mode type Michael Bommarito
@ 2026-05-19 11:04 ` Michael Bommarito
  2026-05-19 12:21   ` Joseph Qi
  2026-06-01 18:21   ` Joel Becker
  2026-05-19 11:04 ` [PATCH v2 3/3] ocfs2: reject non-inline dinodes with i_size and zero i_clusters Michael Bommarito
  2 siblings, 2 replies; 9+ messages in thread
From: Michael Bommarito @ 2026-05-19 11:04 UTC (permalink / raw)
  To: Joseph Qi, Mark Fasheh, Joel Becker
  Cc: ZhengYuan Huang, ocfs2-devel, linux-fsdevel, linux-kernel

id1.dev1.i_rdev is the device-number arm of the ocfs2_dinode id1 union.
It is only meaningful for character and block device inodes. For any
other user-visible file type the on-disk value must be zero.

ocfs2_populate_inode() currently copies id1.dev1.i_rdev into
inode->i_rdev before the S_IFMT switch decides whether the inode is a
special file. A non-device inode with a non-zero i_rdev can therefore
publish stale or attacker-controlled device state into the in-core inode.

System inodes legitimately use other arms of the same union, so keep
the cross-check restricted to non-system inodes. Factor that predicate
into a helper and use it in both the normal validator and online
filecheck path; filecheck reports the malformed dinode through
OCFS2_FILECHECK_ERR_INVALIDINO instead of ocfs2_error().

Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.")
Cc: stable@vger.kernel.org
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Assisted-by: Claude:claude-opus-4-7
---
 fs/ocfs2/inode.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index e149ccbdc03ce..992980ea98046 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -72,6 +72,16 @@ static bool ocfs2_valid_inode_mode(umode_t mode)
 	return fs_umode_to_ftype(mode) != FT_UNKNOWN;
 }
 
+static bool ocfs2_dinode_has_unexpected_rdev(struct ocfs2_dinode *di)
+{
+	umode_t mode = le16_to_cpu(di->i_mode);
+
+	if (le32_to_cpu(di->i_flags) & OCFS2_SYSTEM_FL)
+		return false;
+
+	return !S_ISCHR(mode) && !S_ISBLK(mode) && di->id1.dev1.i_rdev != 0;
+}
+
 void ocfs2_set_inode_flags(struct inode *inode)
 {
 	unsigned int flags = OCFS2_I(inode)->ip_attr;
@@ -1518,6 +1528,41 @@ int ocfs2_validate_inode_block(struct super_block *sb,
 		goto bail;
 	}
 
+	/*
+	 * id1.dev1.i_rdev is the device-number arm of the id1 union and
+	 * is only meaningful for character and block device inodes.  For
+	 * any other regular user-visible file type the on-disk value
+	 * must be zero.  ocfs2_populate_inode() currently runs
+	 *
+	 *     inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
+	 *
+	 * unconditionally, before the S_IFMT switch decides whether the
+	 * inode is a special file.  As a result, an i_rdev value present
+	 * on a non-device inode is silently published into the in-core
+	 * inode; a subsequent forced re-read or in-core mode mutation
+	 * (cluster peer with raw write access to the shared LUN,
+	 * on-disk corruption, or a separately forged dinode) can then
+	 * expose the attacker-controlled device number to
+	 * init_special_inode() without ever showing an unusual i_mode
+	 * at validation time.
+	 *
+	 * System inodes (OCFS2_SYSTEM_FL) legitimately use the bitmap1
+	 * and journal1 arms of the same union (allocator i_used /
+	 * i_total counters and the journal ij_flags /
+	 * ij_recovery_generation pair); those bytes are not an i_rdev
+	 * and must not be checked here.  Restrict the cross-check to
+	 * non-system inodes, which is the full attacker-controllable
+	 * surface.
+	 */
+	if (ocfs2_dinode_has_unexpected_rdev(di)) {
+		rc = ocfs2_error(sb,
+				 "Invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n",
+				 (unsigned long long)bh->b_blocknr,
+				 le16_to_cpu(di->i_mode),
+				 (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
+		goto bail;
+	}
+
 	if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) {
 		struct ocfs2_inline_data *data = &di->id2.i_data;
 
@@ -1657,6 +1702,16 @@ static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
 		     (unsigned long long)bh->b_blocknr,
 		     le16_to_cpu(di->i_mode));
 		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
+		goto bail;
+	}
+
+	if (ocfs2_dinode_has_unexpected_rdev(di)) {
+		mlog(ML_ERROR,
+		     "Filecheck: invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n",
+		     (unsigned long long)bh->b_blocknr,
+		     le16_to_cpu(di->i_mode),
+		     (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
+		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
 	}
 
 bail:
-- 
2.53.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/3] ocfs2: reject non-inline dinodes with i_size and zero i_clusters
  2026-05-19 11:04 [PATCH v2 0/3] ocfs2: harden inode validators against forged metadata Michael Bommarito
  2026-05-19 11:04 ` [PATCH v2 1/3] ocfs2: reject dinodes with non-canonical i_mode type Michael Bommarito
  2026-05-19 11:04 ` [PATCH v2 2/3] ocfs2: reject dinodes whose i_rdev disagrees with the file type Michael Bommarito
@ 2026-05-19 11:04 ` Michael Bommarito
  2026-05-19 12:22   ` Joseph Qi
  2 siblings, 1 reply; 9+ messages in thread
From: Michael Bommarito @ 2026-05-19 11:04 UTC (permalink / raw)
  To: Joseph Qi, Mark Fasheh, Joel Becker
  Cc: ZhengYuan Huang, ocfs2-devel, linux-fsdevel, linux-kernel

On a volume mounted without OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, a
non-inline regular file with non-zero i_size and zero i_clusters is
structurally malformed: the extent map declares no allocated clusters
yet the size header claims content exists.  Keep rejecting that shape,
but express it through a shared predicate so the same invariant is
available to normal inode reads and online filecheck.

The same zero-cluster shape is also malformed for non-inline directories.
ocfs2 directory growth allocates backing storage before advancing
i_size, and ocfs2_dir_foreach_blk_el() later walks until ctx->pos reaches
i_size_read(inode).  A forged directory dinode with a huge i_size and no
clusters would repeatedly fail on holes while advancing through the
claimed size.

Sparse regular files remain exempt: on sparse-alloc volumes, truncate can
legitimately grow i_size without allocating clusters.  System inodes and
inline-data dinodes also retain their separate storage rules.

Mirror the check in ocfs2_filecheck_validate_inode_block() as well.
filecheck reports through its own error namespace, so malformed
size/cluster state is logged as a filecheck invalid-inode result rather
than via ocfs2_error(), but it must not proceed into
ocfs2_populate_inode().

Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.")
Cc: stable@vger.kernel.org
Link: https://sashiko.dev/#/patchset/20260517111015.3187935-1-michael.bommarito%40gmail.com
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Assisted-by: Claude:claude-opus-4-7
---
 fs/ocfs2/inode.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
index 992980ea98046..432eac01c1763 100644
--- a/fs/ocfs2/inode.c
+++ b/fs/ocfs2/inode.c
@@ -82,6 +82,24 @@ static bool ocfs2_dinode_has_unexpected_rdev(struct ocfs2_dinode *di)
 	return !S_ISCHR(mode) && !S_ISBLK(mode) && di->id1.dev1.i_rdev != 0;
 }
 
+static bool ocfs2_dinode_has_size_without_clusters(struct super_block *sb,
+						   struct ocfs2_dinode *di)
+{
+	umode_t mode = le16_to_cpu(di->i_mode);
+
+	if (le32_to_cpu(di->i_flags) & OCFS2_SYSTEM_FL)
+		return false;
+	if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL)
+		return false;
+	if (!le64_to_cpu(di->i_size) || le32_to_cpu(di->i_clusters))
+		return false;
+
+	if (S_ISDIR(mode))
+		return true;
+
+	return !ocfs2_sparse_alloc(OCFS2_SB(sb)) && S_ISREG(mode);
+}
+
 void ocfs2_set_inode_flags(struct inode *inode)
 {
 	unsigned int flags = OCFS2_I(inode)->ip_attr;
@@ -1563,6 +1581,33 @@ int ocfs2_validate_inode_block(struct super_block *sb,
 		goto bail;
 	}
 
+	/*
+	 * Non-inline directories must not have i_size without allocated
+	 * clusters: directory growth adds storage before advancing i_size,
+	 * and readdir walks i_size block-by-block.  A forged directory
+	 * with zero clusters and a huge i_size would repeatedly fault on
+	 * holes while advancing through the claimed size.
+	 *
+	 * Non-inline regular files have the same invariant on non-sparse
+	 * volumes.  Sparse regular files are different: truncate can
+	 * legitimately grow i_size without allocating clusters, so keep
+	 * the sparse-alloc carveout for S_IFREG only.  System inodes and
+	 * inline-data dinodes have their own storage rules.
+	 */
+	if (ocfs2_dinode_has_size_without_clusters(sb, di)) {
+		if (S_ISDIR(le16_to_cpu(di->i_mode)))
+			rc = ocfs2_error(sb,
+					 "Invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n",
+					 (unsigned long long)bh->b_blocknr,
+					 (unsigned long long)le64_to_cpu(di->i_size));
+		else
+			rc = ocfs2_error(sb,
+					 "Invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n",
+					 (unsigned long long)bh->b_blocknr,
+					 (unsigned long long)le64_to_cpu(di->i_size));
+		goto bail;
+	}
+
 	if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) {
 		struct ocfs2_inline_data *data = &di->id2.i_data;
 
@@ -1712,6 +1757,21 @@ static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
 		     le16_to_cpu(di->i_mode),
 		     (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
 		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
+		goto bail;
+	}
+
+	if (ocfs2_dinode_has_size_without_clusters(sb, di)) {
+		if (S_ISDIR(le16_to_cpu(di->i_mode)))
+			mlog(ML_ERROR,
+			     "Filecheck: invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n",
+			     (unsigned long long)bh->b_blocknr,
+			     (unsigned long long)le64_to_cpu(di->i_size));
+		else
+			mlog(ML_ERROR,
+			     "Filecheck: invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n",
+			     (unsigned long long)bh->b_blocknr,
+			     (unsigned long long)le64_to_cpu(di->i_size));
+		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
 	}
 
 bail:
-- 
2.53.0

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/3] ocfs2: reject dinodes with non-canonical i_mode type
  2026-05-19 11:04 ` [PATCH v2 1/3] ocfs2: reject dinodes with non-canonical i_mode type Michael Bommarito
@ 2026-05-19 12:21   ` Joseph Qi
  2026-06-01 18:19   ` Joel Becker
  1 sibling, 0 replies; 9+ messages in thread
From: Joseph Qi @ 2026-05-19 12:21 UTC (permalink / raw)
  To: Michael Bommarito, akpm
  Cc: ZhengYuan Huang, ocfs2-devel, linux-fsdevel, linux-kernel,
	Mark Fasheh, Joel Becker



On 5/19/26 7:04 PM, Michael Bommarito wrote:
> ocfs2_validate_inode_block() currently accepts any non-zero i_mode value.
> ocfs2_populate_inode() then copies that mode verbatim into inode->i_mode
> and dispatches on i_mode & S_IFMT to the file/dir/symlink/special_file
> iops; an unrecognised type falls through to ocfs2_special_file_iops and
> init_special_inode().
> 
> Reject dinodes whose type bits do not name one of the seven canonical
> POSIX file types.  Use fs_umode_to_ftype(), the same generic file-type
> conversion helper OCFS2 already uses for directory entries, so the
> accepted inode type set matches the kernel file-type vocabulary instead
> of open-coding a local switch.
> 
> Apply the same structural check to the online filecheck read path.
> filecheck keeps its own error namespace, so it reports malformed i_mode
> through the filecheck logger and OCFS2_FILECHECK_ERR_INVALIDINO instead
> of calling ocfs2_error(), but it must not allow a malformed dinode to
> proceed into ocfs2_populate_inode().
> 
> Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.")
> Cc: stable@vger.kernel.org
> Link: https://sashiko.dev/#/patchset/20260517111015.3187935-1-michael.bommarito%40gmail.com
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
> Assisted-by: Claude:claude-opus-4-7

Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
> ---
>  fs/ocfs2/inode.c | 36 ++++++++++++++++++++++++++++++++++--
>  1 file changed, 34 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
> index a510a0eb1adcc..e149ccbdc03ce 100644
> --- a/fs/ocfs2/inode.c
> +++ b/fs/ocfs2/inode.c
> @@ -13,6 +13,7 @@
>  #include <linux/pagemap.h>
>  #include <linux/quotaops.h>
>  #include <linux/iversion.h>
> +#include <linux/fs_dirent.h>
>  
>  #include <asm/byteorder.h>
>  
> @@ -64,7 +65,12 @@ static int ocfs2_filecheck_read_inode_block_full(struct inode *inode,
>  static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
>  						struct buffer_head *bh);
>  static int ocfs2_filecheck_repair_inode_block(struct super_block *sb,
> -					      struct buffer_head *bh);
> +						      struct buffer_head *bh);
> +
> +static bool ocfs2_valid_inode_mode(umode_t mode)
> +{
> +	return fs_umode_to_ftype(mode) != FT_UNKNOWN;
> +}
>  
>  void ocfs2_set_inode_flags(struct inode *inode)
>  {
> @@ -1494,6 +1500,24 @@ int ocfs2_validate_inode_block(struct super_block *sb,
>  		goto bail;
>  	}
>  
> +	/*
> +	 * Reject dinodes whose i_mode does not name one of the seven
> +	 * canonical POSIX file types.  ocfs2_populate_inode() copies
> +	 * i_mode verbatim into inode->i_mode and then dispatches via
> +	 * switch (mode & S_IFMT) to file/dir/symlink/special_file iops;
> +	 * an unrecognised type falls into ocfs2_special_file_iops with
> +	 * init_special_inode(), which interprets i_rdev.  Constrain the
> +	 * type here so the dispatch only ever sees a value mkfs.ocfs2 /
> +	 * VFS can produce.
> +	 */
> +	if (!ocfs2_valid_inode_mode(le16_to_cpu(di->i_mode))) {
> +		rc = ocfs2_error(sb,
> +				 "Invalid dinode #%llu: mode 0%o has unknown file type\n",
> +				 (unsigned long long)bh->b_blocknr,
> +				 le16_to_cpu(di->i_mode));
> +		goto bail;
> +	}
> +
>  	if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) {
>  		struct ocfs2_inline_data *data = &di->id2.i_data;
>  
> @@ -1624,6 +1648,15 @@ static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
>  		     (unsigned long long)bh->b_blocknr,
>  		     le32_to_cpu(di->i_fs_generation));
>  		rc = -OCFS2_FILECHECK_ERR_GENERATION;
> +		goto bail;
> +	}
> +
> +	if (!ocfs2_valid_inode_mode(le16_to_cpu(di->i_mode))) {
> +		mlog(ML_ERROR,
> +		     "Filecheck: invalid dinode #%llu: mode 0%o has unknown file type\n",
> +		     (unsigned long long)bh->b_blocknr,
> +		     le16_to_cpu(di->i_mode));
> +		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
>  	}
>  
>  bail:
> @@ -1812,4 +1845,3 @@ const struct ocfs2_caching_operations ocfs2_inode_caching_ops = {
>  	.co_io_lock		= ocfs2_inode_cache_io_lock,
>  	.co_io_unlock		= ocfs2_inode_cache_io_unlock,
>  };
> -


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] ocfs2: reject dinodes whose i_rdev disagrees with the file type
  2026-05-19 11:04 ` [PATCH v2 2/3] ocfs2: reject dinodes whose i_rdev disagrees with the file type Michael Bommarito
@ 2026-05-19 12:21   ` Joseph Qi
  2026-06-01 18:21   ` Joel Becker
  1 sibling, 0 replies; 9+ messages in thread
From: Joseph Qi @ 2026-05-19 12:21 UTC (permalink / raw)
  To: Michael Bommarito, akpm
  Cc: ZhengYuan Huang, ocfs2-devel, linux-fsdevel, linux-kernel,
	Mark Fasheh, Joel Becker



On 5/19/26 7:04 PM, Michael Bommarito wrote:
> id1.dev1.i_rdev is the device-number arm of the ocfs2_dinode id1 union.
> It is only meaningful for character and block device inodes. For any
> other user-visible file type the on-disk value must be zero.
> 
> ocfs2_populate_inode() currently copies id1.dev1.i_rdev into
> inode->i_rdev before the S_IFMT switch decides whether the inode is a
> special file. A non-device inode with a non-zero i_rdev can therefore
> publish stale or attacker-controlled device state into the in-core inode.
> 
> System inodes legitimately use other arms of the same union, so keep
> the cross-check restricted to non-system inodes. Factor that predicate
> into a helper and use it in both the normal validator and online
> filecheck path; filecheck reports the malformed dinode through
> OCFS2_FILECHECK_ERR_INVALIDINO instead of ocfs2_error().
> 
> Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.")
> Cc: stable@vger.kernel.org
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
> Assisted-by: Claude:claude-opus-4-7

Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
> ---
>  fs/ocfs2/inode.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 55 insertions(+)
> 
> diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
> index e149ccbdc03ce..992980ea98046 100644
> --- a/fs/ocfs2/inode.c
> +++ b/fs/ocfs2/inode.c
> @@ -72,6 +72,16 @@ static bool ocfs2_valid_inode_mode(umode_t mode)
>  	return fs_umode_to_ftype(mode) != FT_UNKNOWN;
>  }
>  
> +static bool ocfs2_dinode_has_unexpected_rdev(struct ocfs2_dinode *di)
> +{
> +	umode_t mode = le16_to_cpu(di->i_mode);
> +
> +	if (le32_to_cpu(di->i_flags) & OCFS2_SYSTEM_FL)
> +		return false;
> +
> +	return !S_ISCHR(mode) && !S_ISBLK(mode) && di->id1.dev1.i_rdev != 0;
> +}
> +
>  void ocfs2_set_inode_flags(struct inode *inode)
>  {
>  	unsigned int flags = OCFS2_I(inode)->ip_attr;
> @@ -1518,6 +1528,41 @@ int ocfs2_validate_inode_block(struct super_block *sb,
>  		goto bail;
>  	}
>  
> +	/*
> +	 * id1.dev1.i_rdev is the device-number arm of the id1 union and
> +	 * is only meaningful for character and block device inodes.  For
> +	 * any other regular user-visible file type the on-disk value
> +	 * must be zero.  ocfs2_populate_inode() currently runs
> +	 *
> +	 *     inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
> +	 *
> +	 * unconditionally, before the S_IFMT switch decides whether the
> +	 * inode is a special file.  As a result, an i_rdev value present
> +	 * on a non-device inode is silently published into the in-core
> +	 * inode; a subsequent forced re-read or in-core mode mutation
> +	 * (cluster peer with raw write access to the shared LUN,
> +	 * on-disk corruption, or a separately forged dinode) can then
> +	 * expose the attacker-controlled device number to
> +	 * init_special_inode() without ever showing an unusual i_mode
> +	 * at validation time.
> +	 *
> +	 * System inodes (OCFS2_SYSTEM_FL) legitimately use the bitmap1
> +	 * and journal1 arms of the same union (allocator i_used /
> +	 * i_total counters and the journal ij_flags /
> +	 * ij_recovery_generation pair); those bytes are not an i_rdev
> +	 * and must not be checked here.  Restrict the cross-check to
> +	 * non-system inodes, which is the full attacker-controllable
> +	 * surface.
> +	 */
> +	if (ocfs2_dinode_has_unexpected_rdev(di)) {
> +		rc = ocfs2_error(sb,
> +				 "Invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n",
> +				 (unsigned long long)bh->b_blocknr,
> +				 le16_to_cpu(di->i_mode),
> +				 (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
> +		goto bail;
> +	}
> +
>  	if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) {
>  		struct ocfs2_inline_data *data = &di->id2.i_data;
>  
> @@ -1657,6 +1702,16 @@ static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
>  		     (unsigned long long)bh->b_blocknr,
>  		     le16_to_cpu(di->i_mode));
>  		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
> +		goto bail;
> +	}
> +
> +	if (ocfs2_dinode_has_unexpected_rdev(di)) {
> +		mlog(ML_ERROR,
> +		     "Filecheck: invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n",
> +		     (unsigned long long)bh->b_blocknr,
> +		     le16_to_cpu(di->i_mode),
> +		     (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
> +		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
>  	}
>  
>  bail:


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/3] ocfs2: reject non-inline dinodes with i_size and zero i_clusters
  2026-05-19 11:04 ` [PATCH v2 3/3] ocfs2: reject non-inline dinodes with i_size and zero i_clusters Michael Bommarito
@ 2026-05-19 12:22   ` Joseph Qi
  0 siblings, 0 replies; 9+ messages in thread
From: Joseph Qi @ 2026-05-19 12:22 UTC (permalink / raw)
  To: Michael Bommarito, akpm
  Cc: ZhengYuan Huang, ocfs2-devel, linux-fsdevel, linux-kernel,
	Mark Fasheh, Joel Becker



On 5/19/26 7:04 PM, Michael Bommarito wrote:
> On a volume mounted without OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, a
> non-inline regular file with non-zero i_size and zero i_clusters is
> structurally malformed: the extent map declares no allocated clusters
> yet the size header claims content exists.  Keep rejecting that shape,
> but express it through a shared predicate so the same invariant is
> available to normal inode reads and online filecheck.
> 
> The same zero-cluster shape is also malformed for non-inline directories.
> ocfs2 directory growth allocates backing storage before advancing
> i_size, and ocfs2_dir_foreach_blk_el() later walks until ctx->pos reaches
> i_size_read(inode).  A forged directory dinode with a huge i_size and no
> clusters would repeatedly fail on holes while advancing through the
> claimed size.
> 
> Sparse regular files remain exempt: on sparse-alloc volumes, truncate can
> legitimately grow i_size without allocating clusters.  System inodes and
> inline-data dinodes also retain their separate storage rules.
> 
> Mirror the check in ocfs2_filecheck_validate_inode_block() as well.
> filecheck reports through its own error namespace, so malformed
> size/cluster state is logged as a filecheck invalid-inode result rather
> than via ocfs2_error(), but it must not proceed into
> ocfs2_populate_inode().
> 
> Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.")
> Cc: stable@vger.kernel.org
> Link: https://sashiko.dev/#/patchset/20260517111015.3187935-1-michael.bommarito%40gmail.com
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
> Assisted-by: Claude:claude-opus-4-7

Reviewed-by: Joseph Qi <joseph.qi@linux.alibaba.com>
> ---
>  fs/ocfs2/inode.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 60 insertions(+)
> 
> diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
> index 992980ea98046..432eac01c1763 100644
> --- a/fs/ocfs2/inode.c
> +++ b/fs/ocfs2/inode.c
> @@ -82,6 +82,24 @@ static bool ocfs2_dinode_has_unexpected_rdev(struct ocfs2_dinode *di)
>  	return !S_ISCHR(mode) && !S_ISBLK(mode) && di->id1.dev1.i_rdev != 0;
>  }
>  
> +static bool ocfs2_dinode_has_size_without_clusters(struct super_block *sb,
> +						   struct ocfs2_dinode *di)
> +{
> +	umode_t mode = le16_to_cpu(di->i_mode);
> +
> +	if (le32_to_cpu(di->i_flags) & OCFS2_SYSTEM_FL)
> +		return false;
> +	if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL)
> +		return false;
> +	if (!le64_to_cpu(di->i_size) || le32_to_cpu(di->i_clusters))
> +		return false;
> +
> +	if (S_ISDIR(mode))
> +		return true;
> +
> +	return !ocfs2_sparse_alloc(OCFS2_SB(sb)) && S_ISREG(mode);
> +}
> +
>  void ocfs2_set_inode_flags(struct inode *inode)
>  {
>  	unsigned int flags = OCFS2_I(inode)->ip_attr;
> @@ -1563,6 +1581,33 @@ int ocfs2_validate_inode_block(struct super_block *sb,
>  		goto bail;
>  	}
>  
> +	/*
> +	 * Non-inline directories must not have i_size without allocated
> +	 * clusters: directory growth adds storage before advancing i_size,
> +	 * and readdir walks i_size block-by-block.  A forged directory
> +	 * with zero clusters and a huge i_size would repeatedly fault on
> +	 * holes while advancing through the claimed size.
> +	 *
> +	 * Non-inline regular files have the same invariant on non-sparse
> +	 * volumes.  Sparse regular files are different: truncate can
> +	 * legitimately grow i_size without allocating clusters, so keep
> +	 * the sparse-alloc carveout for S_IFREG only.  System inodes and
> +	 * inline-data dinodes have their own storage rules.
> +	 */
> +	if (ocfs2_dinode_has_size_without_clusters(sb, di)) {
> +		if (S_ISDIR(le16_to_cpu(di->i_mode)))
> +			rc = ocfs2_error(sb,
> +					 "Invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n",
> +					 (unsigned long long)bh->b_blocknr,
> +					 (unsigned long long)le64_to_cpu(di->i_size));
> +		else
> +			rc = ocfs2_error(sb,
> +					 "Invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n",
> +					 (unsigned long long)bh->b_blocknr,
> +					 (unsigned long long)le64_to_cpu(di->i_size));
> +		goto bail;
> +	}
> +
>  	if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) {
>  		struct ocfs2_inline_data *data = &di->id2.i_data;
>  
> @@ -1712,6 +1757,21 @@ static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
>  		     le16_to_cpu(di->i_mode),
>  		     (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
>  		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
> +		goto bail;
> +	}
> +
> +	if (ocfs2_dinode_has_size_without_clusters(sb, di)) {
> +		if (S_ISDIR(le16_to_cpu(di->i_mode)))
> +			mlog(ML_ERROR,
> +			     "Filecheck: invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n",
> +			     (unsigned long long)bh->b_blocknr,
> +			     (unsigned long long)le64_to_cpu(di->i_size));
> +		else
> +			mlog(ML_ERROR,
> +			     "Filecheck: invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n",
> +			     (unsigned long long)bh->b_blocknr,
> +			     (unsigned long long)le64_to_cpu(di->i_size));
> +		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
>  	}
>  
>  bail:


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 1/3] ocfs2: reject dinodes with non-canonical i_mode type
  2026-05-19 11:04 ` [PATCH v2 1/3] ocfs2: reject dinodes with non-canonical i_mode type Michael Bommarito
  2026-05-19 12:21   ` Joseph Qi
@ 2026-06-01 18:19   ` Joel Becker
  1 sibling, 0 replies; 9+ messages in thread
From: Joel Becker @ 2026-06-01 18:19 UTC (permalink / raw)
  To: Michael Bommarito
  Cc: Joseph Qi, Mark Fasheh, ZhengYuan Huang, ocfs2-devel,
	linux-fsdevel, linux-kernel

On Tue, May 19, 2026 at 07:04:02AM -0400, Michael Bommarito wrote:
> ocfs2_validate_inode_block() currently accepts any non-zero i_mode value.
> ocfs2_populate_inode() then copies that mode verbatim into inode->i_mode
> and dispatches on i_mode & S_IFMT to the file/dir/symlink/special_file
> iops; an unrecognised type falls through to ocfs2_special_file_iops and
> init_special_inode().
> 
> Reject dinodes whose type bits do not name one of the seven canonical
> POSIX file types.  Use fs_umode_to_ftype(), the same generic file-type
> conversion helper OCFS2 already uses for directory entries, so the
> accepted inode type set matches the kernel file-type vocabulary instead
> of open-coding a local switch.
> 
> Apply the same structural check to the online filecheck read path.
> filecheck keeps its own error namespace, so it reports malformed i_mode
> through the filecheck logger and OCFS2_FILECHECK_ERR_INVALIDINO instead
> of calling ocfs2_error(), but it must not allow a malformed dinode to
> proceed into ocfs2_populate_inode().
> 
> Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.")
> Cc: stable@vger.kernel.org
> Link: https://sashiko.dev/#/patchset/20260517111015.3187935-1-michael.bommarito%40gmail.com
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
> Assisted-by: Claude:claude-opus-4-7

Reviewed-by: Joel Becker <jlbec@evilplan.org>

Side question: What "Assistance" did Claude provide?  Was the snippet
generated entirely by prompt?  No objection, just curious about the
workflow you're using.

Thanks,
Joel

-- 

"Born under a bad sign.
 I been down since I began to crawl.
 If it wasn't for bad luck,
 I wouldn't have no luck at all."

			http://www.jlbec.org/
			jlbec@evilplan.org

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/3] ocfs2: reject dinodes whose i_rdev disagrees with the file type
  2026-05-19 11:04 ` [PATCH v2 2/3] ocfs2: reject dinodes whose i_rdev disagrees with the file type Michael Bommarito
  2026-05-19 12:21   ` Joseph Qi
@ 2026-06-01 18:21   ` Joel Becker
  1 sibling, 0 replies; 9+ messages in thread
From: Joel Becker @ 2026-06-01 18:21 UTC (permalink / raw)
  To: Michael Bommarito
  Cc: Joseph Qi, Mark Fasheh, ZhengYuan Huang, ocfs2-devel,
	linux-fsdevel, linux-kernel

On Tue, May 19, 2026 at 07:04:03AM -0400, Michael Bommarito wrote:
> id1.dev1.i_rdev is the device-number arm of the ocfs2_dinode id1 union.
> It is only meaningful for character and block device inodes. For any
> other user-visible file type the on-disk value must be zero.
> 
> ocfs2_populate_inode() currently copies id1.dev1.i_rdev into
> inode->i_rdev before the S_IFMT switch decides whether the inode is a
> special file. A non-device inode with a non-zero i_rdev can therefore
> publish stale or attacker-controlled device state into the in-core inode.
> 
> System inodes legitimately use other arms of the same union, so keep
> the cross-check restricted to non-system inodes. Factor that predicate
> into a helper and use it in both the normal validator and online
> filecheck path; filecheck reports the malformed dinode through
> OCFS2_FILECHECK_ERR_INVALIDINO instead of ocfs2_error().
> 
> Fixes: b657c95c1108 ("ocfs2: Wrap inode block reads in a dedicated function.")
> Cc: stable@vger.kernel.org
> Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
> Assisted-by: Claude:claude-opus-4-7

Reviewed-by: Joel Becker <jlbec@evilplan.org>

> ---
>  fs/ocfs2/inode.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 55 insertions(+)
> 
> diff --git a/fs/ocfs2/inode.c b/fs/ocfs2/inode.c
> index e149ccbdc03ce..992980ea98046 100644
> --- a/fs/ocfs2/inode.c
> +++ b/fs/ocfs2/inode.c
> @@ -72,6 +72,16 @@ static bool ocfs2_valid_inode_mode(umode_t mode)
>  	return fs_umode_to_ftype(mode) != FT_UNKNOWN;
>  }
>  
> +static bool ocfs2_dinode_has_unexpected_rdev(struct ocfs2_dinode *di)
> +{
> +	umode_t mode = le16_to_cpu(di->i_mode);
> +
> +	if (le32_to_cpu(di->i_flags) & OCFS2_SYSTEM_FL)
> +		return false;
> +
> +	return !S_ISCHR(mode) && !S_ISBLK(mode) && di->id1.dev1.i_rdev != 0;
> +}
> +
>  void ocfs2_set_inode_flags(struct inode *inode)
>  {
>  	unsigned int flags = OCFS2_I(inode)->ip_attr;
> @@ -1518,6 +1528,41 @@ int ocfs2_validate_inode_block(struct super_block *sb,
>  		goto bail;
>  	}
>  
> +	/*
> +	 * id1.dev1.i_rdev is the device-number arm of the id1 union and
> +	 * is only meaningful for character and block device inodes.  For
> +	 * any other regular user-visible file type the on-disk value
> +	 * must be zero.  ocfs2_populate_inode() currently runs
> +	 *
> +	 *     inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev));
> +	 *
> +	 * unconditionally, before the S_IFMT switch decides whether the
> +	 * inode is a special file.  As a result, an i_rdev value present
> +	 * on a non-device inode is silently published into the in-core
> +	 * inode; a subsequent forced re-read or in-core mode mutation
> +	 * (cluster peer with raw write access to the shared LUN,
> +	 * on-disk corruption, or a separately forged dinode) can then
> +	 * expose the attacker-controlled device number to
> +	 * init_special_inode() without ever showing an unusual i_mode
> +	 * at validation time.
> +	 *
> +	 * System inodes (OCFS2_SYSTEM_FL) legitimately use the bitmap1
> +	 * and journal1 arms of the same union (allocator i_used /
> +	 * i_total counters and the journal ij_flags /
> +	 * ij_recovery_generation pair); those bytes are not an i_rdev
> +	 * and must not be checked here.  Restrict the cross-check to
> +	 * non-system inodes, which is the full attacker-controllable
> +	 * surface.
> +	 */
> +	if (ocfs2_dinode_has_unexpected_rdev(di)) {
> +		rc = ocfs2_error(sb,
> +				 "Invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n",
> +				 (unsigned long long)bh->b_blocknr,
> +				 le16_to_cpu(di->i_mode),
> +				 (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
> +		goto bail;
> +	}
> +
>  	if (le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) {
>  		struct ocfs2_inline_data *data = &di->id2.i_data;
>  
> @@ -1657,6 +1702,16 @@ static int ocfs2_filecheck_validate_inode_block(struct super_block *sb,
>  		     (unsigned long long)bh->b_blocknr,
>  		     le16_to_cpu(di->i_mode));
>  		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
> +		goto bail;
> +	}
> +
> +	if (ocfs2_dinode_has_unexpected_rdev(di)) {
> +		mlog(ML_ERROR,
> +		     "Filecheck: invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n",
> +		     (unsigned long long)bh->b_blocknr,
> +		     le16_to_cpu(di->i_mode),
> +		     (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev));
> +		rc = -OCFS2_FILECHECK_ERR_INVALIDINO;
>  	}
>  
>  bail:
> -- 
> 2.53.0

-- 

"Nearly all men can stand adversity, but if you really want to
 test a man's character, give him power."
	- Abraham Lincoln

			http://www.jlbec.org/
			jlbec@evilplan.org

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-06-01 18:21 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-19 11:04 [PATCH v2 0/3] ocfs2: harden inode validators against forged metadata Michael Bommarito
2026-05-19 11:04 ` [PATCH v2 1/3] ocfs2: reject dinodes with non-canonical i_mode type Michael Bommarito
2026-05-19 12:21   ` Joseph Qi
2026-06-01 18:19   ` Joel Becker
2026-05-19 11:04 ` [PATCH v2 2/3] ocfs2: reject dinodes whose i_rdev disagrees with the file type Michael Bommarito
2026-05-19 12:21   ` Joseph Qi
2026-06-01 18:21   ` Joel Becker
2026-05-19 11:04 ` [PATCH v2 3/3] ocfs2: reject non-inline dinodes with i_size and zero i_clusters Michael Bommarito
2026-05-19 12:22   ` Joseph Qi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox