Skip to content
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

Added sections below image base #4

Open
WhyNotHugo opened this issue May 28, 2023 · 5 comments
Open

Added sections below image base #4

WhyNotHugo opened this issue May 28, 2023 · 5 comments

Comments

@WhyNotHugo
Copy link

WhyNotHugo commented May 28, 2023

Given that gummiboot and other stubs rely on the now-deprecated handover protocol, I'm writing my own little stub loader.

The loader by itself "runs" and can inspect its own PE table to find PE sections (e.g.: the kernel, cmdline, initrd). However, I'm having a hard time assembling a binary which actually contains the stub plus these three.

I'm basically using the following:

efi-mkuki \
  -c /proc/cmdline \
  -o ESP/efi/boot/bootx64.efi \
  -S target/x86_64-unknown-uefi/debug/hello-uefi.efi \
  /efi/vmlinuz-edge \
  /efi/initramfs-edge

Which warns:

objcopy: ESP/efi/boot/bootx64.efi:.osrel: section below image base
objcopy: ESP/efi/boot/bootx64.efi:.cmdline: section below image base
objcopy: ESP/efi/boot/bootx64.efi:.linux: section below image base
objcopy: ESP/efi/boot/bootx64.efi:.initrd: section below image base

Indeed, it seems that the new sections are added to the begging of the file, not to the end of it:

> objdump --section-headers ESP/efi/boot/bootx64.efi                       

ESP/efi/boot/bootx64.efi:     file format pei-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .osrel        000000bc  0000000200020000  0000000200020000  00000400  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  1 .cmdline      000000c2  0000000200030000  0000000200030000  00000600  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .linux        0061ed60  0000000202000000  0000000202000000  00000800  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  3 .initrd       02bdccec  0000000203000000  0000000203000000  0061f600  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .text         00017bf5  0000000140001000  0000000140001000  031fc400  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  5 .rdata        0000423a  0000000140019000  0000000140019000  03214000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .data         00000068  000000014001e000  000000014001e000  03218400  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  7 .eh_fram      00000040  000000014001f000  000000014001f000  03218600  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .reloc        00000314  0000000140020000  0000000140020000  03218800  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

For reference, this is by stub before running mkuki:

> objdump --section-headers target/x86_64-unknown-uefi/debug/hello-uefi.efi 

target/x86_64-unknown-uefi/debug/hello-uefi.efi:     file format pei-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00017bf5  0000000140001000  0000000140001000  00000400  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rdata        0000423a  0000000140019000  0000000140019000  00018000  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         00000068  000000014001e000  000000014001e000  0001c400  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  3 .eh_fram      00000040  000000014001f000  000000014001f000  0001c600  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .reloc        00000314  0000000140020000  0000000140020000  0001c800  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

The resulting binary doesn't run. I'm pretty sure that it is not valid due to the order of the sections (e.g.: the image base should be at the beginning). However, I can't figure out how to force a different order.

For reference, using mkuki with gummiboot's stub results in a different ordering:

> objdump --section-headers EFI/Linux/alpine-edge-6.1.11-0.efi

EFI/Linux/alpine-edge-6.1.11-0.efi:     file format pei-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00005e90  0000000000003000  0000000000003000  00000400  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .reloc        0000000c  0000000000009000  0000000000009000  00006400  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         00001e88  000000000000a000  000000000000a000  00006600  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  3 .dynamic      000000f0  000000000000c000  000000000000c000  00008600  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  4 .rela         00000e58  000000000000d000  000000000000d000  00008800  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .dynsym       000003a8  000000000000e000  000000000000e000  00009800  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  6 .osrel        000000c7  0000000000020000  0000000000020000  00009c00  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  7 .cmdline      000000c2  0000000000030000  0000000000030000  00009e00  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  8 .linux        005d41a0  0000000002000000  0000000002000000  0000a000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  9 .initrd       02b44cd0  0000000003000000  0000000003000000  005de200  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

I tried using objcopy manually, but ended up having the same issue. Any ideas how to address this?

@WhyNotHugo
Copy link
Author

FWIW, I also tried using objcopy directly like this:

objcopy \
  --preserve-dates \
  --enable-deterministic-archives \
  --add-section ".kernel=$KERNEL" --set-section-flags .kernel=code,readonly \
  --add-section ".cmdline=$CMDLINE" --set-section-flags .cmdline=data,readonly \
  --add-section ".initrd=$INITRD" --set-section-flags .initrd=data,readonly \
  target/x86_64-unknown-uefi/debug/hello-uefi.efi \
  ESP/efi/boot/bootx64.efi

But the result in the same.

@WhyNotHugo
Copy link
Author

WhyNotHugo commented May 28, 2023

Looks like --change-section-vma is required (and mkuki is specifying it), but the addresses need to be relative to the ImageBase, which is simply different for my binary:

> objdump -p ESP/efi/boot/bootx64.efi | grep ImageBase
ImageBase		0000000140000000

I'm not sure if I know how to address this in mkuki though, I'll have to do a bit more experimentation first (since I'm manually calculating offsets for now) and adding, for example:

  --add-section ".kernel=$KERNEL" --set-section-flags .kernel=code,readonly --change-section-vma .kernel+0x140020314\

@jas67
Copy link

jas67 commented Aug 26, 2024

@WhyNotHugo -- did you ever figure out how to resolve or work around this problem?

I was successfully using efi-mkuki until changing the kernel that I'm using from 5.15 to 6.8, and my base OS image from Ubuntu 22.04LTS to Ubuntu 24.04LTS.

I now have the object loaded below base error too.

@WhyNotHugo
Copy link
Author

I couldn't figure out how to make this work with efi-mkuki; I still don't fully understand all the parts in play here.

At the time, I wrote my own custom code using a library that handled PE for this. It was a horrible pile of hacks. I can't seem to find any of it now, sorry.

@jas67
Copy link

jas67 commented Aug 27, 2024

I found the problem to be /usr/lib/systemd/boot/efi/linuxx64.efi.stub that is included in Ubuntu 24.04LTS's systemd-efi-bin package. Using this stub to produce the unified kernel image results in the following warning from objcopy:

objcopy:/tmp/NEW_ROOT1224/boot/efi/EFI/ubuntu/vmlinuz.efi:.osrel:sectionbelowimagebase
objcopy:/tmp/NEW_ROOT1224/boot/efi/EFI/ubuntu/vmlinuz.efi:.cmdline:sectionbelowimagebase
objcopy: /tmp/NEW_ROOT1224/boot/efi/EFI/ubuntu/vmlinuz.efi:.linux: section below image base
objcopy:/*mp/NEW_ROOT1224/boot/efi/EFI/ubuntu/vmlinuz.efi:.initrd:section below image base
And the resulting EFI binary will not boot.

If I copied the same file from an Ubuntu 22.04LTS system (in systemd package) and used that instead, I got an EFI binary that boots.

So, at least for now, that is my work-around.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants