XPost: linux.debian.devel.cd
Package: syslinux-efi
Version: 3:6.04~git20190206.bf6db5b4+dfsg1-3.1
Severity: important
Tags: patch
User:
debian-qa@lists.debian.org
Usertags: i386
Dear Maintainer,
While testing syslinux after the FTBFS bugs #994274, #1057462, #1091027,
I discovered that while the BIOS and amd64 EFI versions of the bootloader appear to work fine, the i386 EFI version does not work.
Here are the steps to reproduce:
1. Create new disk image with GPT filesystem and EFI System Partition:
# qemu-img create -f raw syslinux-test.img 64M
# fdisk syslinux-test.img
> g
Created a new GPT disklabel (GUID: 19137FD7-7717-40DB-BC29-5D874A03D0C1).
> n
Partition number (1-128, default 1):
First sector (2048-131038, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-131038, default 129023):
Created a new partition 1 of type 'Linux filesystem' and of size 62 MiB.
> t
Selected partition 1
Partition type or alias (type L to list all): 1
Changed type of partition 'Linux filesystem' to 'EFI System'.
> w
The partition table has been altered.
2. Format EFI System partition as vfat, copy syslinux files:
# modprobe nbd
# qemu-nbd --connect=/dev/nbd0 --format=raw syslinux-test.img
# mkfs.vfat /dev/nbd0p1
# mount /dev/nbd0p1 /mnt/misc
# mkdir -p /mnt/misc/EFI/syslinux
# cp /usr/lib/SYSLINUX.EFI/efi32/syslinux.efi /mnt/misc/EFI/syslinux/
# cp /usr/lib/syslinux/modules/efi32/ldlinux.e32 /mnt/misc/EFI/syslinux/
3. Add 32-bit kernel/initrd files, create syslinux configuration:
# mkdir /mnt/misc/boot
# cp /path/to/vmlinuz /mnt/misc/boot/vmlinuz
# cp /path/to/initrd.img /mnt/misc/boot/initrd.img
# vi /mnt/misc/EFI/syslinux/syslinux.cfg
PROMPT 1
TIMEOUT 50
DEFAULT linux
LABEL linux
KERNEL /boot/vmlinuz
INITRD /boot/initrd.img
4. Use newly created image as qemu hard drive (with ovmf-ia32 firmware):
# umount /mnt/misc
# qemu-nbd -d /dev/nbd0
$ cp /usr/share/OVMF/OVMF32_CODE_4M.fd .
$ cp /usr/share/OVMF/OVMF32_VARS_4M.fd .
$ qemu-system-i386 -m 128 -net none \
-drive file=OVMF32_CODE_4M.fd,format=raw,if=pflash \
-drive file=OVMF32_VARS_4M.fd,format=raw,if=pflash \
-drive format=raw,file=syslinux-test.img \
-chardev file,id=char0,path=serial.dump -serial chardev:char0
Shell> FS0:\EFI\syslinux\syslinux.efi
Expected outcome (upstream 6.03 build from kernel.org):
syslinux starts up and allows me to boot the provided kernel/initrd files.
Outcome with 3:6.04~git20190206.bf6db5b4+dfsg1-3.1 from Debian Unstable:
syslinux moves the cursor on-screen and then returns back to the EFI Shell.
I've spent some time debugging this, and ended up discovering that there is
a separate bug with message generation in early EFI syslinux, I'll open
a separate bug for that, but it turns out that a message actually is written
in the case where it apparently just moves the cursor, it's just that
the message has black-on-black coloring, thus being invisible.
The message can be extracted from the serial line dump by passing it through ansi2txt:
$ ansi2txt < serial.dump > serial.log
Here, we see that the issue has to do with loading ldlinux.e32:
$ tail -n4 serial.log
Shell> FS0:\EFI\syslinux\syslinux.efi
Failed to load ldlinux.e32
Shell>
I've spent some time debugging this, and it turns out that there's a problem with the ELF loader where it doesn't handle zero-sized program segments correctly.
While iterating through the program headers in the load_segments() function
in com32/lib/sys/module/i386/elf_module.c, the code encounters a header
with a target a target virtual address of 0x0001d000, a size of 0,
and a p_offset (section offset within file) of 0.
Looking at objdump, this is the .bss section, which means that the above information is valid:
$ objdump -x efi32/com32/elflink/ldlinux/ldlinux.e32
...
Sections:
Idx Name Size VMA LMA File off Algn
16 .bss 000030fc 0001d000 0001d000 0001d000 2**5
ALLOC
Interestingly enough, objdump reports the section file offset as non-zero,
so there has to be a difference between how the two ELF library implementations evaluate that field, but it doesn't matter, since according to the SystemV ABI document, chapter 5 [0], when there is a difference between the section size and its on-disk size, the amount of bytes that are specified in p_filesz
are loaded from file:p_offset to module_base+p_vaddr and the rest is filled with zeroes.
The ELF loading code in syslinux does initialize the memory to zero,
so the only thing we need to do is handle situations when there is nothing
to load from the section.
I'm attaching a patch that adds two checks for this. The first check is
a general "skip zero-sized sections" check, the second check is for
the partial section load branch, where it checks to see if there is
anything to load instead of just blindly subtracting an aux offset from
the section size and potentially getting a integer underflow, resulting
in a 4GiB load request (this is actually what happened).
With the patch, it seems to work fine, and the bootloader successfully boots the provided kernel and initrd (TinyCore Linux in my testing).
Best Regards,
Marek
[0]:
https://refspecs.linuxbase.org/elf/gabi4+/ch5.pheader.html
-- System Information:
Debian Release: trixie/sid
APT prefers testing
APT policy: (500, 'testing')
Architecture: amd64 (x86_64)
Kernel: Linux 6.14.2 (SMP w/16 CPU threads; PREEMPT)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled
syslinux-efi depends on no packages.
Versions of packages syslinux-efi recommends:
ii syslinux-common 3:6.04~git20190206.bf6db5b4+dfsg1-3.1
Versions of packages syslinux-efi suggests:
ii dosfstools 4.2-1.2
-- no debconf information
LS0tIHN5c2xpbnV4LTYuMDR+Z2l0MjAxOTAyMDYuYmY2ZGI1YjQrZGZzZzEub3JpZy9jb20zMi9s aWIvc3lzL21vZHVsZS9pMzg2L2VsZl9tb2R1bGUuYw0KKysrIHN5c2xpbnV4LTYuMDR+Z2l0MjAx OTAyMDYuYmY2ZGI1YjQrZGZzZzEvY29tMzIvbGliL3N5cy9tb2R1bGUvaTM4Ni9lbGZfbW9kdWxl LmMNCkBAIC0xMTIsNiArMTEyLDE0IEBAIGludCBsb2FkX3NlZ21lbnRzKHN0cnVjdCBlbGZfbW9k dWxlICptb2QNCiAJZm9yIChpID0gMDsgaSA8IGVsZl9oZHItPmVfcGhudW07IGkrKykgew0KIAkJ Y3JfcGh0ID0gKEVsZjMyX1BoZHIqKShwaHQgKyBpICogZWxmX2hkci0+ZV9waGVudHNpemUpOw0K IA0KKwkJaWYgKGNyX3BodC0+cF9maWxlc3ogPT0gMCkNCisJCXsNCisJCQlEQkdfUFJJTlQoIlNr aXBwaW5nIGxvYWRhYmxlIHNlZ21lbnQgb2YgemVybyBzaXplIGF0IHZhZGRyIDB4JTA4eCBhdCAw eCUwOHguXG4iDQorCQkJCQljcl9waHQtPnBfdmFkZHIsDQorCQkJCQkoRWxmMzJfQWRkciltb2R1 bGVfZ2V0X2Fic29sdXRlKGNyX3BodC0+cF92YWRkciwgbW9kdWxlKSk7DQorCQkJY29udGludWU7 DQorCQl9DQorDQogCQlpZiAoY3JfcGh0LT5wX3R5cGUgPT0gUFRfTE9BRCkgew0KIAkJCS8vIENv cHkgdGhlIHNlZ21lbnQgYXQgaXRzIGRlc3RpbmF0aW9uDQogCQkJaWYgKGNyX3BodC0+cF9vZmZz ZXQgPCBtb2R1bGUtPnUubC5fY3Jfb2Zmc2V0KSB7DQpAQCAtMTIwLDYgKzEyOCwxNiBAQCBpbnQg bG9hZF9zZWdtZW50cyhzdHJ1Y3QgZWxmX21vZHVsZSAqbW9kDQogCQkJCS8vIGhlYWRlcnMNCiAJ CQkJRWxmMzJfT2ZmIGF1eF9vZmYgPSBtb2R1bGUtPnUubC5fY3Jfb2Zmc2V0IC0gY3JfcGh0LT5w X29mZnNldDsNCiANCisJCQkJaWYgKGNyX3BodC0+cF9maWxlc3ogPD0gYXV4X29mZikNCisJCQkJ ew0KKwkJCQkJREJHX1BSSU5UKCJTa2lwcGluZyBzZWdtZW50IG9mIHNpemUgMHglMDh4IGF0IHZh ZGRyIDB4JTA4eCBhdCAweCUwOHgsICINCisJCQkJCSAgICAgICAgICAiYWxsIGRhdGEgaXMgYmVm b3JlIGN1cnJlbnQgb2Zmc2V0LlxuIiwNCisJCQkJCQkJY3JfcGh0LT5wX2ZpbGVzeiwNCisJCQkJ CQkJY3JfcGh0LT5wX3ZhZGRyLA0KKwkJCQkJCQkoRWxmMzJfQWRkciltb2R1bGVfZ2V0X2Fic29s dXRlKGNyX3BodC0+cF92YWRkciwgbW9kdWxlKSk7DQorCQkJCQljb250aW51ZTsNCisJCQkJfQ0K Kw0KIAkJCQlpZiAoaW1hZ2VfcmVhZCgoY2hhciAqKW1vZHVsZV9nZXRfYWJzb2x1dGUoY3JfcGh0 LT5wX3ZhZGRyLCBtb2R1bGUpICsgYXV4X29mZiwNCiAJCQkJCSAgICAgICBjcl9waHQtPnBfZmls ZXN6IC0gYXV4X29mZiwgbW9kdWxlKSA8IDApIHsNCiAJCQkJCXJlcyA9IC0xOw0KLS0tIHN5c2xp bnV4LTYuMDR+Z2l0MjAxOTAyMDYuYmY2ZGI1YjQrZGZzZzEub3JpZy9jb20zMi9saWIvc3lzL21v ZHVsZS94ODZfNjQvZWxmX21vZHVsZS5jDQorKysgc3lzbGludXgtNi4wNH5naXQyMDE5MDIwNi5i ZjZkYjViNCtkZnNnMS9jb20zMi9saWIvc3lzL21vZHVsZS94ODZfNjQvZWxmX21vZHVsZS5jDQpA QCAtMTEyLDYgKzExMiwxNCBAQCBpbnQgbG9hZF9zZWdtZW50cyhzdHJ1Y3QgZWxmX21vZHVsZSAq bW9kDQogCWZvciAoaSA9IDA7IGkgPCBlbGZfaGRyLT5lX3BobnVtOyBpKyspIHsNCiAJCWNyX3Bo dCA9IChFbGY2NF9QaGRyKikocGh0ICsgaSAqIGVsZl9oZHItPmVfcGhlbnRzaXplKTsNCiANCisJ CWlmIChjcl9waHQtPnBfZmlsZXN6ID09IDApDQorCQl7DQorCQkJREJHX1BSSU5UKCJTa2lwcGlu ZyBsb2FkYWJsZSBzZWdtZW50IG9mIHplcm8gc2l6ZSBhdCB2YWRkciAweCUwOHggYXQgMHglMDh4 LlxuIg0KKwkJCQkJY3JfcGh0LT5wX3ZhZGRyLA0KKwkJCQkJKEVsZjMyX0FkZHIpbW9kdWxlX2dl dF9hYnNvbHV0ZShjcl9waHQtPnBfdmFkZHIsIG1vZHVsZSkpOw0KKwkJCWNvbnRpbnVlOw0KKwkJ fQ0KKw0KIAkJaWYgKGNyX3BodC0+cF90eXBlID09IFBUX0xPQUQpIHsNCiAJCQkvLyBDb3B5IHRo ZSBzZWdtZW50IGF0IGl0cyBkZXN0aW5hdGlvbg0KIAkJCWlmIChjcl9waHQtPnBfb2Zmc2V0IDwg bW9kdWxlLT51LmwuX2NyX29mZnNldCkgew0KQEAgLTEyMCw2ICsxMjgsMTYgQEAgaW50IGxvYWRf c2VnbWVudHMoc3RydWN0IGVsZl9tb2R1bGUgKm1vZA0KIAkJCQkvLyBoZWFkZXJzDQogCQkJCUVs ZjY0X09mZiBhdXhfb2ZmID0gbW9kdWxlLT51LmwuX2NyX29mZnNldCAtIGNyX3BodC0+cF9vZmZz ZXQ7DQogDQorCQkJCWlmIChjcl9waHQtPnBfZmlsZXN6IDw9IGF1eF9vZmYpDQorCQkJCXsNCisJ CQkJCURCR19QUklOVCgiU2tpcHBpbmcgc2VnbWVudCBvZiBzaXplIDB4JTA4eCBhdCB2YWRkciAw eCUwOHggYXQgMHglMDh4LCAiDQorCQkJCQkgICAgICAgICAgImFsbCBkYXRhIGlzIGJlZm9yZSBj dXJyZW50IG9mZnNldC5cbiIsDQorCQkJCQkJCWNyX3BodC0+cF9maWxlc3osDQorCQkJCQkJCWNy X3BodC0+cF92YWRkciwNCisJCQkJCQkJKEVsZjMyX0FkZHIpbW9kdWxlX2dldF9hYnNvbHV0ZShj cl9waHQtPnBfdmFkZHIsIG1vZHVsZSkpOw0KKwkJCQkJY29udGludWU7DQorCQkJCX0NCisNCiAJ CQkJaWYgKGltYWdlX3JlYWQoKGNoYXIgKiltb2R1bGVfZ2V0X2Fic29sdXRlKGNyX3BodC0+cF92 YWRkciwgbW9kdWxlKSArIGF1eF9vZmYsDQogCQkJCQkgICAgICAgY3JfcGh0LT5wX2ZpbGVzeiAt IGF1eF9vZmYsIG1vZHVsZSkgPCAwKSB7DQogCQkJCQlyZXMgPSAtMTsNCg==
--- SoupGate-Win32 v1.05
* Origin: fsxNet Usenet Gateway (21:1/5)