diff --git a/src/conf.h b/src/conf.h index 911979ed..93c8d44f 100644 --- a/src/conf.h +++ b/src/conf.h @@ -516,6 +516,7 @@ struct options_t { } tos; struct { unsigned blocksize; + bool force_execve; // force the linux/386 execve format enum { SCRIPT_MAX = 32 }; const char *script_name; } unix; diff --git a/src/main.cpp b/src/main.cpp index a37d3e74..60dbbc9f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -637,6 +637,9 @@ static int do_option(int optc, const char *arg) getoptvar(&opt->unix.blocksize, 8192u, ~0u); break; case 661: + opt->unix.force_execve = true; + break; + case 662: opt->unix.script_name = "/usr/local/lib/upx/upxX"; if (mfx_optarg && mfx_optarg[0]) set_script_name(mfx_optarg,1); @@ -742,8 +745,9 @@ static const struct mfx_option longopts[] = // dos/sys // unix {"blocksize", 0x31, 0, 660}, // --blocksize= + {"force-execve", 0x10, 0, 661}, // force linux/386 execve format #if 0 - {"script", 0x31, 0, 661}, // --script= + {"script", 0x31, 0, 662}, // --script= #endif // watcom/le {"le", 0, 0, 620}, // produce LE output diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 892b51c5..ac09c65b 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -173,19 +173,13 @@ bool PackLinuxI386elf::canPack() fi->readx(buf, sizeof(buf)); fi->seek(0, SEEK_SET); - if (0 != memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) // ELF 32-bit LSB - return false; + Elf_LE32_Ehdr const *const ehdr = (Elf_LE32_Ehdr const *)buf; // now check the ELF header - Elf_LE32_Ehdr const *const ehdr = (Elf_LE32_Ehdr const *)buf; - if (memcmp(buf+8, "FreeBSD", 7) == 0) // branded as FreeBSD - return false; - if (ehdr->e_type != 2) // executable - return false; - if (ehdr->e_machine != 3 && ehdr->e_machine != 6) // Intel 80[34]86 - return false; - if (ehdr->e_version != 1) // version + if (checkEhdr(ehdr) != 0) return false; + + // additional requirements for linux/elf386 if (ehdr->e_ehsize != sizeof(*ehdr)) { throwCantPack("invalid Ehdr e_ehsize"); return false; diff --git a/src/p_lx_exc.cpp b/src/p_lx_exc.cpp index 3214fc77..c71af26f 100644 --- a/src/p_lx_exc.cpp +++ b/src/p_lx_exc.cpp @@ -88,6 +88,31 @@ int PackLinuxI386::getLoaderPrefixSize() const // **************************************************************************/ +// basic check of an Linux ELF Ehdr +int PackLinuxI386::checkEhdr(const Elf_LE32_Ehdr *ehdr) const +{ + const unsigned char * const buf = ehdr->e_ident; + + // NOTE: ELF executables are now handled by p_lx_elf.cpp. + if (memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) // ELF 32-bit LSB + return -1; + + // FIXME: add special checks for uncompresed "vmlinux" kernel + // now check the ELF header + if (!memcmp(buf+8, "FreeBSD", 7)) // branded + return 1; + if (ehdr->e_type != 2) // executable + return 2; + if (ehdr->e_machine != 3 && ehdr->e_machine != 6) // Intel 80[34]86 + return 3; + if (ehdr->e_version != 1) // version + return 4; + + // success + return 0; +} + + bool PackLinuxI386::canPack() { if (exetype != 0) @@ -101,25 +126,16 @@ bool PackLinuxI386::canPack() exetype = 0; const unsigned l = get_le32(buf); -#if 0 - // NOTE: ELF executables are now handled by p_lx_elf.cpp. - if (!memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) // ELF 32-bit LSB + + int elf = checkEhdr(&ehdr); + if (elf >= 0) { - // FIXME: add special checks for uncompresed "vmlinux" kernel - exetype = 1; - // now check the ELF header - if (!memcmp(buf+8, "FreeBSD", 7)) // branded - exetype = 0; - if (ehdr.e_type != 2) // executable - exetype = 0; - if (ehdr.e_machine != 3 && ehdr.e_machine != 6) // Intel 80[34]86 - exetype = 0; - if (ehdr.e_version != 1) // version - exetype = 0; + // NOTE: ELF executables are now handled by p_lx_elf.cpp, + // so we only handle them here if force_execve + if (elf == 0 && opt->unix.force_execve) + exetype = 1; } - else -#endif - if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc) + else if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc) { // OMAGIC / NMAGIC / ZMAGIC / QMAGIC exetype = 2; diff --git a/src/p_lx_exc.h b/src/p_lx_exc.h index f37c39e1..5d98db0d 100644 --- a/src/p_lx_exc.h +++ b/src/p_lx_exc.h @@ -50,6 +50,8 @@ protected: virtual int getLoaderSize() const; virtual int getLoaderPrefixSize() const; + virtual int checkEhdr(const Elf_LE32_Ehdr *ehdr) const; + virtual void patchLoader(); virtual void patchLoaderChecksum(); virtual void updateLoader(OutputFile *); diff --git a/src/packmast.cpp b/src/packmast.cpp index 1b5afdb5..2ab08bdd 100644 --- a/src/packmast.cpp +++ b/src/packmast.cpp @@ -185,17 +185,20 @@ static Packer* try_packers(InputFile *f, try_function func) // // linux // -#if 0 - if (opt->unix.script_name) + if (!opt->unix.force_execve) { - if ((p = func(new PackLinuxI386sep(f),f)) != NULL) +#if 0 + if (opt->unix.script_name) + { + if ((p = func(new PackLinuxI386sep(f),f)) != NULL) + return p; + } +#endif + if ((p = func(new PackLinuxI386elf(f),f)) != NULL) + return p; + if ((p = func(new PackLinuxI386sh(f),f)) != NULL) return p; } -#endif - if ((p = func(new PackLinuxI386elf(f),f)) != NULL) - return p; - if ((p = func(new PackLinuxI386sh(f),f)) != NULL) - return p; if ((p = func(new PackLinuxI386(f),f)) != NULL) return p;