grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Proposal v2: fs/iso9660: Prevent skipping CE or ST at start of conti


From: Thomas Schmitt
Subject: Re: Proposal v2: fs/iso9660: Prevent skipping CE or ST at start of continuation area
Date: Mon, 09 Jan 2023 10:32:48 +0100

Hi,

Lidong Chen wrote:
> Thanks for the clarification. I created a new patch for the fix and added
> you as the “Signed-off-by”.
> My question is how to test it.

I just sent libisofs into an endless recursion loop. Grrr.
For this i created a small ISO with a file which surely needs a CE, changed
its fields so that it points to itself, and attempted to load it by xorriso.
(At least it ends by SIGSEGV on an exhausted stack and does not cycle
endlessly.)

--------------------------------------------------------------------------
ISO creation:

   # A dummy file as payload
   echo x >x

   # 250 fattr characters to surely exceed the size of a directory entry
   
long_string=0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789

   # Create ISO with the payload file and attached fattr named user.dummy
   test -e ce_loop.iso && rm ce_loop.iso
   xorriso -outdev ce_loop.iso \
           -xattr on \
           -map x /x \
           -setfattr user.dummy "$long_string" /x -- \
           -padding 0

Next i determined by a hex dumper the location of the only Rock Ridge
entry NM and then the location of the next following CE entry (the first
CE belongs to the root directory):
  Byte 102734 decimal = 50 * 2048 + 334 = LBA 0x32 + Offset 0x014e
The size of the continuation area is 270 = 0x010e
The length of CE is 28 = 0x1c

So i patched the own address and size of the CE entry into its fields:

  # The block address (little endian and big endian)
  echo $'\x32' | dd bs=1 seek=102738 count=1 conv=notrunc of=ce_loop.iso
  echo $'\x32' | dd bs=1 seek=102745 count=1 conv=notrunc of=ce_loop.iso

  # The byte offset in that block
  echo $'\x4e'$'\x01' | dd bs=1 seek=102746 count=2 conv=notrunc of=ce_loop.iso
  echo $'\x01'$'\x4e' | dd bs=1 seek=102752 count=2 conv=notrunc of=ce_loop.iso

  # The new size of the CE area is the length of the CE entry
  echo $'\x1c' | dd bs=1 seek=102754 count=1 conv=notrunc of=ce_loop.iso
  echo $'\x1c' | dd bs=1 seek=102761 count=1 conv=notrunc of=ce_loop.iso
  # Zeroize the higher valued bytes of the length field
  dd if=/dev/zero bs=1 seek=102755 count=6 conv=notrunc of=ce_loop.iso

This really bad CE entry then looks in the hex dump like:

00019140 :    00  7b  01  09  08  08  1c  00  4e  4d  06  01  00  78  43  45
                   {                           N   M               x   C   E
  102720 :     0 123   1   9   8   8  28   0  78  77   6   1   0 120  67  69

00019150 :    1c  01  32  00  00  00  00  00  00  32  4e  01  00  00  00  00
                       2                           2   N
  102736 :    28   1  50   0   0   0   0   0   0  50  78   1   0   0   0   0

00019160 :    01  4e  1c  00  00  00  00  00  00  1c  00  00  00  00  00  00
                   N
  102752 :     1  78  28   0   0   0   0   0   0  28   0   0   0   0   0   0

(Note: 00019140 is hex, not octal)

--------------------------------------------------------------------------

I will first try to fix libisofs before i upload this gremlin somewhere.

If you want to try in advance, run above shell commands and check whether
a hex editor shows the expected bytes afterwards. (xorriso is supposed to
be reproducible in respect to sizes and locations. Very old versions might
not fulfill that expectation, though.)


Have a nice day :)

Thomas




reply via email to

[Prev in Thread] Current Thread [Next in Thread]