]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
isofs: validate Rock Ridge CE continuation extent against volume size
authorMichael Bommarito <michael.bommarito@gmail.com>
Sun, 19 Apr 2026 21:21:54 +0000 (17:21 -0400)
committerJan Kara <jack@suse.cz>
Mon, 20 Apr 2026 14:53:17 +0000 (16:53 +0200)
rock_continue() reads rs->cont_extent verbatim from the Rock Ridge CE
record and passes it to sb_bread() without checking that the block
number is within the mounted ISO 9660 volume.  commit e595447e177b
("[PATCH] rock.c: handle corrupted directories") added cont_offset
and cont_size rejection for the CE continuation but did not validate
the extent block number itself.  commit f54e18f1b831 ("isofs: Fix
infinite looping over CE entries") later capped the CE chain length
at RR_MAX_CE_ENTRIES = 32 but again left the block number unchecked.

With a crafted ISO mounted via udisks2 (desktop optical auto-mount)
or via CAP_SYS_ADMIN mount, rs->cont_extent can therefore point at
an out-of-range block or at blocks belonging to an adjacent
filesystem on the same block device.  sb_bread() on an out-of-range
block returns NULL cleanly via the block layer EIO path, so there
is no memory-safety violation.  For in-range reads of adjacent-
filesystem data, the CE buffer is parsed as Rock Ridge records and
only the text of SL sub-records reaches userspace through
readlink(), which makes the info-leak channel narrow and difficult
to exploit; still, rejecting the malformed CE outright matches the
rejection shape already present in the same function for
cont_offset and cont_size.

Add an ISOFS_SB(sb)->s_nzones bounds check to rock_continue() next
to the existing offset/size rejection, printing the same
corrupted-directory-entry notice.

Fixes: f54e18f1b831 ("isofs: Fix infinite looping over CE entries")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Michael Bommarito <michael.bommarito@gmail.com>
Link: https://patch.msgid.link/20260419212155.2169382-2-michael.bommarito@gmail.com
Signed-off-by: Jan Kara <jack@suse.cz>
fs/isofs/rock.c

index 6fe6dbd0c740f7c739cf9de6ee68cb3bfc552e21..1232fab59a4e68f8d5db0c95c474864d6f0eb0c9 100644 (file)
@@ -101,6 +101,15 @@ static int rock_continue(struct rock_state *rs)
                goto out;
        }
 
+       if ((unsigned)rs->cont_extent >= ISOFS_SB(rs->inode->i_sb)->s_nzones) {
+               printk(KERN_NOTICE "rock: corrupted directory entry. "
+                       "extent=%u out of volume (nzones=%lu)\n",
+                       (unsigned)rs->cont_extent,
+                       ISOFS_SB(rs->inode->i_sb)->s_nzones);
+               ret = -EIO;
+               goto out;
+       }
+
        if (rs->cont_extent) {
                struct buffer_head *bh;