[syslinux] isolinux.bin checksum
Thomas Schmitt
scdbackup at gmx.net
Tue Jan 9 08:41:52 PST 2018
Hi,
i think i found a suspect in lzo/prepcore.c and it would indeed be a
wrong range of checksumming (speculative congratulations to Ady).
Looking at
http://repo.or.cz/syslinux.git/blob/0d82b71304d596d80f3c4520f9dcf90048ca50b7:/lzo/prepcore.c
it seems that this change in line 374 could yield correct checksums:
unsigned int ptr;
- for (ptr = 64; ptr < offset; ptr += 4)
+ for (ptr = start+64; ptr < offset; ptr += 4)
csum += get_32((uint32_t *)(infile+ptr));
A test whether it works would be to produce isolinux.bin, read the 4 checksum
bytes from it at offset 20, put isolinux.bin into an ISO with mkisofs option
-boot-info-table, and check whether the 4 bytes at offset 20 are still the
same.
(If you use mkisofs or genisoimage, isolinux.bin on hard disk will change.
With xorrisofs the change will only appear in the file isolinux.bin in the
ISO filesystem.)
--------------------------------------------------------------------------
Reasoning:
- The prescription for Boot Info Table says that checksumming begins
at byte 64 of isolinux.bin. (See for example man mkisofs paragraph
"EL TORITO BOOT INFORMATION TABLE".)
- prepcore.c constructs isolinux.bin from an unencrypted piece out of
the input file isolinux.raw (which stems from an objcopy -S run) and
from a compressed part.
So it begins to compute the checksum on the input file bytes
for (ptr = 64; ptr < offset; ptr += 4)
csum += get_32((uint32_t *)(infile+ptr));
and then continues on the compressed part
for (ptr = 0; ptr < outfile_len; ptr += 4)
csum += get_32((uint32_t *)(out+ptr));
- But prepcore.c copies infile data to isolinux.bin starting with an
offset named "start" which i strongly believe is not zero:
if (fwrite(infile+start,1,offset-start,f) != offset-start ||
If "start" is not zero, then this is not the same byte range as with
the checksum loop over (infile+ptr).
- "start" obviously is used to skip at least the 32 byte header which
prepcore.c interprets at the beginning of the input file:
struct prefix {
uint32_t pfx_start;
uint32_t pfx_compressed;
uint32_t pfx_cdatalen;
uint32_t pfx_checksum;
};
...
struct prefix *prefix;
...
infile_len = (lzo_uint) fread(infile,1,infile_len,f);
...
prefix = (struct prefix *)infile;
start = get_32(&prefix->pfx_start);
offset = get_32(&prefix->pfx_compressed);
Such header bytes with plausible values are not to see at the beginning of
isolinux.bin:
fa ea 6c 7c 00 00 90 90 10 00 00 00 00 00 00 00
The struct members pfx_start and pfx_compressed are read as little endian
unsigned integers and used as offsets in the isolinux.raw file.
0x7c6ceafa and 0x90900000 are much too large to have served for that
purpose.
So the original prefix header was skipped, and thus "start" was not zero.
Have a nice day :)
Thomas
More information about the Syslinux
mailing list