Skip to content

pycdlib.pycdlibexception.PyCdlibInvalidISO: Unused fields should be 0 opening FreeBSD 14.3-BETA1 ISO #136

@emaste

Description

@emaste

We had a report of a pycdlib exception opening the FreeBSD 14.3 BETA1 amd64 ISO image FreeBSD-14.3-BETA1-amd64-dvd1.iso. FreeBSD PR: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=286666

The report we received contained this exception trace:

"/tmp/ansible_community.general.iso_customize_payload_ymbwbmqn/ansible_community.general.iso_customize_payload.zip/ansible_collections/community/general/plugins/modules/iso_customize.py", line 271, in iso_rebuild
  File "/usr/local/lib/python3.10/dist-packages/pycdlib/pycdlib.py", line 4152, in open
    self._open_fp(fp)
  File "/usr/local/lib/python3.10/dist-packages/pycdlib/pycdlib.py", line 2320, in _open_fp
    ic_level, lastbyte = self._walk_directories(self.pvd, extent_to_ptr,
  File "/usr/local/lib/python3.10/dist-packages/pycdlib/pycdlib.py", line 1066, in _walk_directories
    rr = new_record.parse(vd, data[offset:offset + lenbyte],
  File "/usr/local/lib/python3.10/dist-packages/pycdlib/dr.py", line 284, in parse
    if xa_rec.parse(record[record_offset:], self.len_fi):
  File "/usr/local/lib/python3.10/dist-packages/pycdlib/dr.py", line 88, in parse
    raise pycdlibexception.PyCdlibInvalidISO('Unused fields should be 0')

XARecord::parse() has this logic:

        even_size = len_fi + (len_fi % 2)
        # In a "typical" XA record, the record immediately follows the DR
        # record (but comes before the Rock Ridge record, if this is a Rock
        # Ridge ISO).  However, we have seen ISOs (Windows 98 SE) that put some
        # padding between the end of the DR record and the XA record.  As far
        # as I can tell, that padding is the size of the file identifier,
        # but rounded up to the nearest even number.  We check both places for
        # the XA record.
        for offset in (0, even_size):
            parse_str = xastr[offset:]
            if len(parse_str) < struct.calcsize(self.FMT):
                return False

            (self._group_id, self._user_id, self._attributes, signature,
             self._filenum, unused) = struct.unpack_from(self.FMT, parse_str, 0)
            if signature != b'XA':
                continue

            if unused != b'\x00\x00\x00\x00\x00':
                raise pycdlibexception.PyCdlibInvalidISO('Unused fields should be 0')

            self._pad_size = offset
            break
        else:
            return False

A hexdump of a portion of our ISO image is:

000b7800  a8 00 56 d4 1a 00 00 1a  d4 56 08 0a 00 00 00 00  |..V......V......|
000b7810  0a 08 7d 05 02 0c 2f 34  00 00 00 00 01 00 00 01  |..}.../4........|
000b7820  1e 53 53 4c 5f 53 45 53  53 49 4f 4e 5f 47 45 54  |.SSL_SESSION_GET|
000b7830  30 5f 54 49 43 4b 45 54  2e 33 5f 47 5a 3b 31 00  |0_TICKET.3_GZ;1.|
000b7840  50 58 2c 01 24 81 00 00  00 00 81 24 03 00 00 00  |PX,.$......$....|
000b7850  00 00 00 03 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000b7860  00 00 00 00 58 41 00 00  00 00 41 58 54 46 1a 01  |....XA....AXTF..|
000b7870  0e 7d 05 02 0c 2f 34 00  7d 05 02 0c 2f 34 00 7d  |.}.../4.}.../4.}|
000b7880  05 02 0c 30 08 00 4e 4d  21 01 00 53 53 4c 5f 53  |...0..NM!..SSL_S|
000b7890  45 53 53 49 4f 4e 5f 67  65 74 30 5f 74 69 63 6b  |ESSION_get0_tick|
000b78a0  65 74 2e 33 2e 67 7a 00  b2 00 9b d3 1a 00 00 1a  |et.3.gz.........|
000b78b0  d3 9b a0 10 00 00 00 00  10 a0 7d 05 02 0c 2f 33  |..........}.../3|

The Rock Ridge PX record happens to have the two bytes 0x58 0x41 (XA) in its data and pycdlib falsely detects that as a corrupt XA record.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions