* [PATCH] freevxfs: reject invalid OLT record sizes
@ 2026-07-22 10:57 Sangho Lee
2026-07-22 12:10 ` Christoph Hellwig
0 siblings, 1 reply; 3+ messages in thread
From: Sangho Lee @ 2026-07-22 10:57 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-kernel, Sangho Lee, stable
vxfs_read_olt() walks image-controlled Object Location Table records by
adding each record's on-disk olt_size to the current cursor:
oaddr += fs32_to_cpu(infp, ocp->olt_size);
The value is not checked before it is used. A crafted VxFS image can set a
record size to zero, which prevents the cursor from advancing and leaves
mount(2) spinning in the kernel. Oversized values can also move the cursor
past the mapped OLT block without first rejecting the malformed image.
Reject malformed OLT header and record sizes before using them. A valid
header must place the first record after the header and within the mapped
OLT extent. Each record must be at least large enough to contain the common
record header and must fit in the remaining extent.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Sangho Lee <kudo3228@gmail.com>
---
fs/freevxfs/vxfs_olt.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
index 23f35187c289..e5fb3b86d88e 100644
--- a/fs/freevxfs/vxfs_olt.c
+++ b/fs/freevxfs/vxfs_olt.c
@@ -56,6 +56,7 @@
struct buffer_head *bp;
struct vxfs_olt *op;
char *oaddr, *eaddr;
+ u32 olt_size;
bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
if (!bp || !bp->b_data)
@@ -77,12 +78,21 @@
goto fail;
}
- oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size);
eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
+ olt_size = fs32_to_cpu(infp, op->olt_size);
+ if (olt_size < sizeof(*op) || olt_size > eaddr - bp->b_data) {
+ pr_notice("vxfs: invalid olt header size\n");
+ goto fail;
+ }
+ oaddr = bp->b_data + olt_size;
while (oaddr < eaddr) {
struct vxfs_oltcommon *ocp =
(struct vxfs_oltcommon *)oaddr;
+ u32 rec_size = fs32_to_cpu(infp, ocp->olt_size);
+
+ if (rec_size < sizeof(*ocp) || rec_size > eaddr - oaddr)
+ goto fail;
switch (fs32_to_cpu(infp, ocp->olt_type)) {
case VXFS_OLT_FSHEAD:
@@ -93,7 +103,11 @@
break;
}
- oaddr += fs32_to_cpu(infp, ocp->olt_size);
+ /*
+ * rec_size has already been checked to advance oaddr and stay
+ * within the mapped OLT extent.
+ */
+ oaddr += rec_size;
}
brelse(bp);
--
2.43.0
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] freevxfs: reject invalid OLT record sizes
2026-07-22 10:57 [PATCH] freevxfs: reject invalid OLT record sizes Sangho Lee
@ 2026-07-22 12:10 ` Christoph Hellwig
2026-07-22 14:39 ` Sangho Lee
0 siblings, 1 reply; 3+ messages in thread
From: Christoph Hellwig @ 2026-07-22 12:10 UTC (permalink / raw)
To: Sangho Lee; +Cc: Christoph Hellwig, linux-kernel, stable
On Wed, Jul 22, 2026 at 07:57:06PM +0900, Sangho Lee wrote:
> vxfs_read_olt() walks image-controlled Object Location Table records by
> adding each record's on-disk olt_size to the current cursor:
>
> oaddr += fs32_to_cpu(infp, ocp->olt_size);
>
> The value is not checked before it is used. A crafted VxFS image can set a
> record size to zero, which prevents the cursor from advancing and leaves
> mount(2) spinning in the kernel. Oversized values can also move the cursor
> past the mapped OLT block without first rejecting the malformed image.
>
> Reject malformed OLT header and record sizes before using them. A valid
> header must place the first record after the header and within the mapped
> OLT extent. Each record must be at least large enough to contain the common
> record header and must fit in the remaining extent.
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Cc: stable@vger.kernel.org
> Signed-off-by: Sangho Lee <kudo3228@gmail.com>
> ---
> fs/freevxfs/vxfs_olt.c | 17 +++++++++++++++--
> 1 file changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/fs/freevxfs/vxfs_olt.c b/fs/freevxfs/vxfs_olt.c
> index 23f35187c289..e5fb3b86d88e 100644
> --- a/fs/freevxfs/vxfs_olt.c
> +++ b/fs/freevxfs/vxfs_olt.c
> @@ -56,6 +56,7 @@
> struct buffer_head *bp;
> struct vxfs_olt *op;
> char *oaddr, *eaddr;
> + u32 olt_size;
>
> bp = sb_bread(sbp, vxfs_oblock(sbp, infp->vsi_oltext, bsize));
> if (!bp || !bp->b_data)
> @@ -77,12 +78,21 @@
> goto fail;
> }
>
> - oaddr = bp->b_data + fs32_to_cpu(infp, op->olt_size);
> eaddr = bp->b_data + (infp->vsi_oltsize * sbp->s_blocksize);
> + olt_size = fs32_to_cpu(infp, op->olt_size);
> + if (olt_size < sizeof(*op) || olt_size > eaddr - bp->b_data) {
> + pr_notice("vxfs: invalid olt header size\n");
> + goto fail;
> + }
> + oaddr = bp->b_data + olt_size;
>
> while (oaddr < eaddr) {
> struct vxfs_oltcommon *ocp =
> (struct vxfs_oltcommon *)oaddr;
> + u32 rec_size = fs32_to_cpu(infp, ocp->olt_size);
Overly long line.
Otherwise this does looks sane, but given that freevxfs had
exactly one user in the last 20 years, what is the point?
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] freevxfs: reject invalid OLT record sizes
2026-07-22 12:10 ` Christoph Hellwig
@ 2026-07-22 14:39 ` Sangho Lee
0 siblings, 0 replies; 3+ messages in thread
From: Sangho Lee @ 2026-07-22 14:39 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Sangho Lee, linux-kernel, stable
Thanks for the review.
I agree that freevxfs has extremely limited usage. My rationale was that the
filesystem remains buildable in mainline and a malformed image causes a
deterministic unbounded loop during mount. The fix is small and ensures that
the on-disk record walk always makes progress.
If you think freevxfs should no longer receive this kind of hardening, I will
not pursue the patch further. Otherwise, I can send a v2 with the line wrapped.
Thanks,
Sangho
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-22 14:39 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-22 10:57 [PATCH] freevxfs: reject invalid OLT record sizes Sangho Lee
2026-07-22 12:10 ` Christoph Hellwig
2026-07-22 14:39 ` Sangho Lee
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®