New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
compute the bootloader stage size to workaround PIE #30
Conversation
pie.sh.gz - a script to reproduce the mentioned behaviour |
https://github.com/ibm-s390-tools/s390-tools/blob/master/zipl/src/boot.c#L41 is the location of the failing checks |
This happens to work:
But I think it will break if the file size is odd because on S/390, all global objects must have even addresses. The right solution seems to be to use |
Hi, sorry for the late reply. Just for my understanding: You do not replace the CFLAGS, don't you? Overall, for me it feels strange to not have the corresponding linker flag set to the -fno-pie CFLAG. |
We set the CFLAGS/CXXFLAGS/LDFLAGS to a distro defined ones (https://src.fedoraproject.org/rpms/s390utils/blob/master/f/s390utils.spec#_91) as they are a superset of the upstream ones. zipl itself has 2 parts - first is the "boot records" in zipl/boot and it filters out any "pie" flags, they correctly use "CFLAGS_BOOT" in https://github.com/ibm-s390-tools/s390-tools/blob/master/zipl/boot/Makefile. These boot records are then transformed into "data" that are bundled to the user-space zipl binary. The user-space zipl is built with distro CFLAGS/LDFLAGS that include PIE. The whole build log is at https://kojipkgs.fedoraproject.org//packages/s390utils/2.4.0/1.fc29/data/logs/s390x/build.log As a whole I think we use the distro *FLAGS as consistent as possible in s390-tools. |
OK, thanks for clarification. |
Looks like a problem in Binutils :( An ld optimization rewrites a GOT access with lgrl r1, x@GOTENT to larl r1, x if it detects the symbol being referenced locally. Bug 1 is that it does this also for SHN_ABS symbols. Bug 2 is that it doesn't even check whether the symbol resides at an even address. I'll fix this in Binutils. However, as an Binutils-independent fix I agree that the proposal from Florian is a nice way to solve it. I don't think we really have to care about odd lengths here since the boot loader stages are generated from .S files and gas will pad the sections to a 4 byte boundary. Longterm I think it would be better to include the bootloader code into the zipl binary using the .incbin gas directive in an inline assembly in the code. Labels around it could be used to perform the size sanity checking. |
I finally got around to fixing this in mainline Binutils: |
Thanks. In Ubuntu, I have PIE disabled for zipl as well. I don't think many bootloader code is PIE capable. I think we disable it for a few of bootloader-like things i.e. qemu firmwares, and the like. |
PIE (and hardening in general) is enabled in the user-space zipl command line tool, not in the actual bootloader, which uses its own set of compiler flags anyway. |
This should allow building the user-space zipl correctly with PIE. Fedora embeds the hardening flags in the compiler and linker flags, so after fixing https://bugzilla.redhat.com/show_bug.cgi?id=1552661 zipl started to fail with "Error: Internal error: Size mismatch of FBA stage 0 loader".
The bootloader stages run during IPL are built with their own flags and converted to raw binaries. These binaries are then converted to ELF objects with objdump and linked together to create data.o and data.h files (see boot/Makefile). During the bin->ELF conversion 3 symbols are added - start, end and size. When zipl is built with PIE the "size" symbols is relocated and the comparisons in boot_check_data() fail. "size" is marked as ABS in readelf output, so maybe there is also a binutils/linker bug. At the end instead of using the provided "size" we compute that from the "end" and "start" pointers and all seems to work correctly.
The command line we use to build zipl (and the whole s390-tools) is