JonathonReinhart / staticx

Create static executable from dynamic executable
https://staticx.readthedocs.io/
Other
345 stars 37 forks source link

staticx: Bootloader machine (EM_X86_64) doesn't match program machine (EM_AARCH64) #181

Closed alsf2001 closed 2 years ago

alsf2001 commented 3 years ago

i run staticx on a arm machine, but get the follow result, how to fix it staticx: Bootloader machine (EM_X86_64) doesn't match program machine (EM_AARCH64)

JonathonReinhart commented 3 years ago

Hi @alsf2001 -- thanks for the bug report.

It appears that you're trying to use staticx on a cross-compiled binary -- meaning, you're running on an x86-64 host, but you're working with an aarch64 binary.

Unfortunately, StaticX doesn't currently support operating in a cross-architecture manner.

JonathonReinhart commented 3 years ago

I'm closing this in favor of #182.

JonathonReinhart commented 3 years ago

i run staticx on a arm machine,

I apologize, I missed this part. Can you please tell me how you installed staticx?

Assuming you ran pip3 install staticx: Looking at the published files:

So I'm at a loss.

JonathonReinhart commented 3 years ago

@alsf2001 Any feedback? If not, I'll go ahead and close the issue. Thanks.

Jongy commented 3 years ago

@JonathonReinhart , not entirely related to cross building but this is the only issue mentioning Aarch64 so I thought to ask here first.

I can confirm that staticx works just fine when running on an Aarch64 machine. As you mentioned, there's no wheel for Aarch64 so it gets built locally. However, when running the staticx build in a Dockerfile cross-built on x86_64, the resulting binary crashes with SIGSEGV. It runs just fine when I tried it with gdb. The stack trace from gdb and a core file (generated in a "clean" run) is:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x0000ffffa4909848 in __GI___libc_malloc (bytes=472) at malloc.c:3056
3056    malloc.c: No such file or directory.
(gdb) bt
#0  0x0000ffffa4909848 in __GI___libc_malloc (bytes=472) at malloc.c:3056
#1  0x0000ffffa48f4058 in __fopen_internal (filename=0xffffa4a093c0 "/etc/passwd", mode=0xffffa4a09240 "rce", is32=1) at iofopen.c:58
#2  0x0000ffffa4a05ff8 in internal_setent (stream=0xfffff4062180) at nss_files/files-XXX.c:77
#3  0x0000ffffa4a06204 in _nss_files_getpwnam_r (name=0xc144111 "root", result=0x4c2a08 <resbuf>, buffer=0xc144220 "", buflen=1024, errnop=0xc13b720) at nss_files/files-pwd.c:32
#4  0x00000000004362b4 in getpwnam_r ()
#5  0x0000000000435f5c in getpwnam ()
#6  0x0000000000404d0c in th_get_uid (t=0xc143ff0) at libtar/decode.c:49
#7  0x0000000000403c0c in th_print_long_ls (t=0xc143ff0, f=0x4c0040 <_IO_2_1_stderr_>) at libtar/output.c:51
#8  0x00000000004039b0 in tar_extract_all (t=0xc143ff0, prefix=0xc13cb30 "/tmp/staticx-7eHn81") at libtar/extract.c:552
#9  0x0000000000401ac0 in extract_archive (dest_path=0xc13cb30 "/tmp/staticx-7eHn81") at bootloader/extract.c:229
#10 0x0000000000402950 in main (argc=1, argv=0xfffff40635f8) at bootloader/main.c:423

Deeming this as some type of heap corruption, I also tried valgrind but it runs successfully as well haha. I also tried building the bootloader with -fsanitize=address but my GCC was too old for that.

My suspicion is that something doesn't get emulated correctly and the bootloader is built with semi-correct settings (some parameters still fitting x86_64 and not Aarch64), which results in the corruption.

I might find some time to continue investigating this in the weekend, meanwhile if you have any suggestions where to continue searching, I'd be happy to hear them :)

For reference - I ran my tests basing on the image centos@sha256:43964203bf5d7fe38c6fca6166ac89e4c095e2b0c0a28f6c7c678a1348ddc7fa (installing everything for staticx + latest staticx from pypi)

Jongy commented 3 years ago

Hmm, I realized it's just related to CentOS - this Dockerfile yields a binary crashing with the same stack, when built on Linux xxx 5.8.0-1035-aws #37~20.04.1-Ubuntu SMP Tue Jun 1 09:52:32 UTC 2021 aarch64 aarch64 aarch64 GNU/Linux.

# centos:7
FROM centos@sha256:43964203bf5d7fe38c6fca6166ac89e4c095e2b0c0a28f6c7c678a1348ddc7fa AS build-stage

RUN cat /etc/os-release;

RUN yum install -y gcc python3 curl python3-pip python3-devel

RUN python3 -m pip install wheel scons
RUN yum install -y glibc-static
RUN python3 -m pip install staticx

RUN yum install -y bzip2
RUN curl -o /tmp/patchelf-0.13.tar.bz2  -sSL https://github.com/NixOS/patchelf/releases/download/0.13/patchelf-0.13.tar.bz2
RUN yum install -y make
RUN yum install -y gcc-c++
RUN cd /tmp && tar -jxf patchelf-0.13.tar.bz2 && cd patchelf* && ./configure  --disable-dependency-tracking && make install

RUN echo 'void main() { printf("hello world!\n"); return 0; }' > a.c && gcc a.c -o a
RUN staticx a /a_static

FROM scratch AS export-stage

COPY --from=build-stage /a_static /a_static

when building locally on that Ubuntu machine, everything works. So I assume the issue is with CentOS.

JonathonReinhart commented 2 years ago

@Jongy I think you have a valid StaticX bug there. There's zero reason the statically-linked bootloader should crash. Can you please open a new issue with your findings? Specifically:

Thanks. I'm closing this (unrelated) issue.

Jongy commented 2 years ago

@Jongy I think you have a valid StaticX bug there. There's zero reason the statically-linked bootloader should crash. Can you please open a new issue with your findings? Specifically:

  • Open a new issue whose body is your first post
  • Add a comment with your second post

Thanks. I'm closing this (unrelated) issue.

Sure thing, will do that right away.