All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ufs: reject malformed cylinder summary geometry
@ 2026-07-01 21:57 이상호
  0 siblings, 0 replies; only message in thread
From: 이상호 @ 2026-07-01 21:57 UTC (permalink / raw)
  To: Kees Cook, Al Viro; +Cc: 이상호, linux-fsdevel, linux-kernel

ufs_read_cylinder_structures() allocates uspi->s_cssize bytes for the
cylinder summary area, but it calculates the number of fragments to copy
using the on-disk fs_fshift value and then copies a full s_fsize bytes for
every fragment:

	size = uspi->s_cssize;
	blks = (size + uspi->s_fsize - 1) >> uspi->s_fshift;
	base = space = kmalloc(size, GFP_NOFS);
	...
	memcpy(space, bh->b_data, uspi->s_fsize);

ufs_fill_super() validates fs_fsize, but not the sibling fs_fshift and
fs_cssize fields. A crafted writable UFS/FFS image can therefore set an
inconsistent fs_fshift, or set fs_cssize to a value that does not match the
number of cylinder groups, causing the loop to copy past the end of the
allocated cylinder summary buffer.

Reject inconsistent cylinder summary geometry before writable mount. This
preserves the existing read/write paths for valid filesystems and fails
malformed superblocks before ufs_read_cylinder_structures() can overrun the
kmalloc(s_cssize) buffer.

This matches normal producer output: UFS/FFS tools derive fs_fshift from
fs_fsize and round the cylinder summary table size up to a fragment
boundary.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: 이상호 <kudo3228@gmail.com>
---
Notes:
- Public third-party writeup for the same issue:
  https://psn.af/k/17/
- Unpatched CONFIG_UFS_FS_WRITE=y KASAN replay reproduces the
  ufs_read_cylinder_structures slab-out-of-bounds write.
- Patched replay rejects the malformed image with EINVAL before the
  vulnerable copy loop; no UFS KASAN signature appears.
- The same patch applies cleanly with git apply --check to checked
  mainline/stable refs: origin/master, linux-6.18.y, linux-6.12.y,
  linux-6.6.y, linux-6.1.y, linux-5.15.y, and linux-5.10.y.
- A latest-master raw-source patchcheck also reports vulnerable_shape=present
  and patch_status=applies for fs/ufs/super.c.
- Full logs and reproducer image are available privately on request.

 fs/ufs/super.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/fs/ufs/super.c b/fs/ufs/super.c
index c4831a8b9b3f..c295b637920a 100644
--- a/fs/ufs/super.c
+++ b/fs/ufs/super.c
@@ -725,6 +725,7 @@ static int ufs_fill_super(struct super_block *sb, struct fs_context *fc)
 	struct ufs_buffer_head * ubh;	
 	struct inode *inode;
 	unsigned block_size, super_block_size;
+	u64 expected_cssize;
 	unsigned flags;
 	unsigned super_block_offset;
 	unsigned maxsymlen;
@@ -1139,6 +1140,19 @@ static int ufs_fill_super(struct super_block *sb, struct fs_context *fc)
 		uspi->s_csaddr = fs32_to_cpu(sb, usb1->fs_csaddr);
 
 	uspi->s_cssize = fs32_to_cpu(sb, usb1->fs_cssize);
+	if (uspi->s_fshift != ilog2(uspi->s_fsize)) {
+		pr_err("%s(): fragment size/shift mismatch (%u/%u)\n",
+		       __func__, uspi->s_fsize, uspi->s_fshift);
+		goto failed;
+	}
+	expected_cssize = (u64)uspi->s_ncg * sizeof(struct ufs_csum);
+	expected_cssize = (expected_cssize + uspi->s_fsize - 1) &
+		~((u64)uspi->s_fsize - 1);
+	if (!uspi->s_cssize || uspi->s_cssize != expected_cssize) {
+		pr_err("%s(): invalid cylinder summary size %u (expected %llu)\n",
+		       __func__, uspi->s_cssize, expected_cssize);
+		goto failed;
+	}
 	uspi->s_cgsize = fs32_to_cpu(sb, usb1->fs_cgsize);
 	uspi->s_ntrak = fs32_to_cpu(sb, usb1->fs_ntrak);
 	uspi->s_nsect = fs32_to_cpu(sb, usb1->fs_nsect);
-- 
2.43.0

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-07-01 21:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01 21:57 [PATCH] ufs: reject malformed cylinder summary geometry 이상호

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.