Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Updated patches for new file format.
  • Loading branch information
icculus committed Sep 17, 2009
1 parent 2b03ad7 commit 478ac2a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 59 deletions.
40 changes: 19 additions & 21 deletions patches/glibc.diff
@@ -1,11 +1,5 @@
commit 0591028b61bb19b35bdb4d92e0feab1cccc8afc1
Author: Ryan C. Gordon <icculus@icculus.org>
Date: Wed Sep 16 19:57:31 2009 -0400

FatELF support for glibc-2.9

diff --git a/elf/dl-load.c b/elf/dl-load.c
index 0b896d9..bbf6138 100644
index 0b896d9..4a44c41 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -27,6 +27,7 @@
Expand Down Expand Up @@ -51,7 +45,7 @@ index 0b896d9..bbf6138 100644
== MAP_FAILED))
goto map_error;

@@ -1551,6 +1553,83 @@ print_search_path (struct r_search_path_elem **list,
@@ -1551,6 +1553,85 @@ print_search_path (struct r_search_path_elem **list,
_dl_debug_printf_c ("\t\t(%s)\n", what);
}

Expand Down Expand Up @@ -108,13 +102,15 @@ index 0b896d9..bbf6138 100644
+
+ /* the only fields any of the elf_machine_matches_host()s care about. */
+ ehdr.e_machine = (ElfW(Half)) le16_to_cpu(record->machine);
+ ehdr.e_ident[EI_OSABI] = record->osabi;
+ ehdr.e_ident[EI_ABIVERSION] = record->osabi_version;
+ ehdr.e_ident[EI_CLASS] = record->word_size;
+ ehdr.e_ident[EI_DATA] = record->byte_order;
+
+ /* if we fail a test here, we just jump to the next record. */
+ if (!VALID_ELF_OSABI(le16_to_cpu(record->osabi)))
+ if (!VALID_ELF_OSABI(record->osabi))
+ continue;
+ else if (!VALID_ELF_ABIVERSION(le16_to_cpu(record->osabi_version)))
+ else if (!VALID_ELF_ABIVERSION(record->osabi_version))
+ continue;
+ else if (!elf_machine_matches_host(&ehdr))
+ continue;
Expand All @@ -135,7 +131,7 @@ index 0b896d9..bbf6138 100644
/* Open a file and verify it is an ELF file for this architecture. We
ignore only ELF files for other architectures. Non-ELF files and
ELF files with different header information cause fatal errors since
@@ -1561,13 +1640,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
@@ -1561,13 +1642,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
int whatcode, bool *found_other_class, bool free_name)
{
/* This is the expected ELF header. */
Expand All @@ -150,7 +146,7 @@ index 0b896d9..bbf6138 100644
MORE_ELF_HEADER_DATA;
#endif
static const unsigned char expected[EI_PAD] =
@@ -1632,6 +1705,11 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
@@ -1632,6 +1707,11 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,

/* This is where the ELF header is loaded. */
assert (sizeof (fbp->buf) > sizeof (ElfW(Ehdr)));
Expand All @@ -162,7 +158,7 @@ index 0b896d9..bbf6138 100644
ehdr = (ElfW(Ehdr) *) fbp->buf;

/* Now run the tests. */
@@ -1727,7 +1805,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
@@ -1727,7 +1807,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
else
{
phdr = alloca (maplength);
Expand All @@ -171,7 +167,7 @@ index 0b896d9..bbf6138 100644
if ((size_t) __libc_read (fd, (void *) phdr, maplength) != maplength)
{
read_error:
@@ -1748,7 +1826,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
@@ -1748,7 +1828,7 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
else
{
abi_note = alloca (size);
Expand All @@ -181,10 +177,10 @@ index 0b896d9..bbf6138 100644
goto read_error;
}
diff --git a/elf/elf.h b/elf/elf.h
index ce6de07..6789c1d 100644
index ce6de07..d4216b0 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -61,6 +61,32 @@ typedef uint16_t Elf64_Section;
@@ -61,6 +61,34 @@ typedef uint16_t Elf64_Section;
typedef Elf32_Half Elf32_Versym;
typedef Elf64_Half Elf64_Versym;

Expand All @@ -195,11 +191,13 @@ index ce6de07..6789c1d 100644
+/* FatELF values on disk are always littleendian, and align like Elf64. */
+typedef struct
+{
+ uint16_t osabi;
+ uint16_t osabi_version;
+ uint16_t machine;
+ uint8_t word_size;
+ uint8_t byte_order;
+ uint16_t machine; /* maps to e_machine */
+ uint8_t osabi; /* maps to e_ident[EI_OSABI] */
+ uint8_t osabi_version; /* maps to e_ident[EI_ABIVERSION] */
+ uint8_t word_size; /* maps to e_ident[EI_CLASS] */
+ uint8_t byte_order; /* maps to e_ident[EI_DATA] */
+ uint8_t reserved0;
+ uint8_t reserved1;
+ uint64_t offset;
+ uint64_t size;
+} fatelf_record;
Expand Down
71 changes: 33 additions & 38 deletions patches/linux-kernel.diff
Expand Up @@ -18,7 +18,7 @@ index f92bdaa..6753d45 100644

#define cpu_uses_ia32el() (local_cpu_data->family > 0x1f)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 7c1e65d..93181d3 100644
index 7c1e65d..d90c55f 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -37,8 +37,9 @@
Expand Down Expand Up @@ -88,7 +88,7 @@ index 7c1e65d..93181d3 100644
total_size = 0;
if (!*interp_map_addr)
*interp_map_addr = map_addr;
@@ -560,6 +565,113 @@ static unsigned long randomize_stack_top(unsigned long stack_top)
@@ -560,6 +565,97 @@ static unsigned long randomize_stack_top(unsigned long stack_top)
#endif
}

Expand All @@ -110,12 +110,9 @@ index 7c1e65d..93181d3 100644
+ *elf = *((struct elfhdr *)buf); /* treat like normal ELF. */
+ return 0; /* not a FatELF binary; not an error. */
+ } else if (unlikely(le16_to_cpu(fatelf->version) != 1)) {
+ printk(KERN_INFO "FATELF: '%s' is FatELF, but wrong version! (%d)\n", filename, (int) (le16_to_cpu(fatelf->version)));
+ return -ENOEXEC; /* Unrecognized format version. */
+ }
+
+ printk(KERN_INFO "FATELF: '%s' is FatELF!\n", filename);
+
+ /*
+ * In theory, there could be 255 separate records packed into this
+ * binary, but for now, bprm->buf (128 bytes) holds exactly 5
Expand All @@ -124,16 +121,14 @@ index 7c1e65d..93181d3 100644
+ * if there's a serious need.
+ */
+ records = (int) fatelf->num_records; /* uint8, no byteswap needed */
+ printk(KERN_INFO "FATELF: '%s' has %d records.\n", filename, records);
+
+ if (unlikely(records > 5)) {
+ printk(KERN_INFO "FATELF: '%s' clamped to 5 records.\n", filename);
+ records = 5; /* clamp, in case we find one we can use. */
+ }
+
+ for (i = 0; i < records; i++) {
+ const fatelf_record *record = &fatelf->records[i];
+ const __u16 osabi = le16_to_cpu(record->osabi);
+ const __u8 osabi = record->osabi;
+ const int abiok = likely( likely(osabi == ELFOSABI_NONE) ||
+ unlikely(osabi == ELFOSABI_LINUX) );
+
Expand All @@ -143,13 +138,10 @@ index 7c1e65d..93181d3 100644
+ elf->e_machine = le16_to_cpu(record->machine);
+
+ if (likely(!elf_check_arch(elf))) {
+ printk(KERN_INFO "FATELF: '%s' arch %d unsupported.\n", filename, elf->e_machine);
+ continue; /* Unsupported CPU architecture. */
+ } else if (unlikely(!abiok)) {
+ printk(KERN_INFO "FATELF: '%s' osabi %d unsupported.\n", filename, (int) osabi);
+ continue; /* Unsupported OS ABI. */
+ } else if (unlikely(le16_to_cpu(record->osabi_version) != 0)) {
+ printk(KERN_INFO "FATELF: '%s' osabi %d unsupported.\n", filename, (int) le16_to_cpu(record->osabi_version));
+ } else if (unlikely(record->osabi_version != 0)) {
+ continue; /* Unsupported OS ABI version. */
+ } else {
+ /* We can support this ELF arch/abi. */
Expand All @@ -158,29 +150,22 @@ index 7c1e65d..93181d3 100644
+ const __u64 end_offset = rec_offset + rec_size;
+ const unsigned long uloff = (unsigned long) rec_offset;
+
+ printk(KERN_INFO "FATELF: '%s' arch %d IS supported.\n", filename, elf->e_machine);
+
+ /* check for overflow conditions (corrupt file?)... */
+ if (unlikely(end_offset < rec_offset)) {
+ printk(KERN_INFO "FATELF: '%s' arch %d overflow!\n", filename, elf->e_machine);
+ continue;
+ }
+
+#if BITS_PER_LONG == 32
+ else if (unlikely(end_offset > 0xFFFFFFFF)) {
+ printk(KERN_INFO "FATELF: '%s' arch %d 32-bit overflow!\n", filename, elf->e_machine);
+ continue;
+ }
+#endif
+
+ /* make sure we're correctly aligned. */
+ else if (unlikely(ELF_PAGEOFFSET(uloff) != 0)) {
+ printk(KERN_INFO "FATELF: '%s' arch %d is misaligned!\n", filename, elf->e_machine);
+ continue;
+ }
+
+ printk(KERN_INFO "FATELF: '%s' offset %lu size %lu.\n", filename, uloff, (unsigned long) rec_size);
+
+ /* replace the FatELF data with the real ELF header. */
+ rc = kernel_read(file, uloff, (char*) elf, sizeof(*elf));
+ if (unlikely((rc != sizeof(*elf)) && (rc >= 0))) {
Expand All @@ -190,7 +175,6 @@ index 7c1e65d..93181d3 100644
+ rc = 0;
+ }
+
+ printk(KERN_INFO "FATELF: '%s' returning %d (offset %lu)\n", filename, rc, *offset);
+ return rc;
+ }
+ }
Expand All @@ -202,7 +186,7 @@ index 7c1e65d..93181d3 100644
static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
{
struct file *interpreter = NULL; /* to shut gcc up */
@@ -571,6 +683,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
@@ -571,6 +667,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
unsigned long elf_bss, elf_brk;
int retval, i;
unsigned int size;
Expand All @@ -211,7 +195,7 @@ index 7c1e65d..93181d3 100644
unsigned long elf_entry;
unsigned long interp_load_addr = 0;
unsigned long start_code, end_code, start_data, end_data;
@@ -587,9 +701,12 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
@@ -587,9 +685,12 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
retval = -ENOMEM;
goto out_ret;
}
Expand All @@ -227,7 +211,7 @@ index 7c1e65d..93181d3 100644

retval = -ENOEXEC;
/* First of all, some simple consistency checks */
@@ -615,7 +732,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
@@ -615,7 +716,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
if (!elf_phdata)
goto out;

Expand All @@ -236,7 +220,7 @@ index 7c1e65d..93181d3 100644
(char *)elf_phdata, size);
if (retval != size) {
if (retval >= 0)
@@ -649,7 +766,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
@@ -649,7 +750,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
if (!elf_interpreter)
goto out_free_ph;

Expand All @@ -246,7 +230,7 @@ index 7c1e65d..93181d3 100644
elf_interpreter,
elf_ppnt->p_filesz);
if (retval != elf_ppnt->p_filesz) {
@@ -704,8 +822,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
@@ -704,8 +806,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
goto out_free_dentry;
}

Expand All @@ -262,7 +246,16 @@ index 7c1e65d..93181d3 100644
break;
}
elf_ppnt++;
@@ -830,7 +953,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
@@ -779,7 +886,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)

if (unlikely (elf_brk > elf_bss)) {
unsigned long nbyte;
-
+
/* There was a PT_LOAD segment with p_memsz > p_filesz
before this one. Map anonymous pages, if needed,
and clear the area. */
@@ -830,7 +937,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
}

error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
Expand All @@ -271,7 +264,7 @@ index 7c1e65d..93181d3 100644
if (BAD_ADDR(error)) {
send_sig(SIGKILL, current, 0);
retval = IS_ERR((void *)error) ?
@@ -894,7 +1017,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
@@ -894,7 +1001,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
* mapping in the interpreter, to make sure it doesn't wind
* up getting placed where the bss needs to go.
*/
Expand All @@ -280,7 +273,7 @@ index 7c1e65d..93181d3 100644
if (retval) {
send_sig(SIGKILL, current, 0);
goto out_free_dentry;
@@ -911,7 +1034,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
@@ -911,7 +1018,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
elf_entry = load_elf_interp(&loc->interp_elf_ex,
interpreter,
&interp_map_addr,
Expand All @@ -289,7 +282,7 @@ index 7c1e65d..93181d3 100644
if (!IS_ERR((void *)elf_entry)) {
/*
* load_elf_interp() returns relocation
@@ -1026,11 +1149,19 @@ static int load_elf_library(struct file *file)
@@ -1026,11 +1133,19 @@ static int load_elf_library(struct file *file)
unsigned long elf_bss, bss, len;
int retval, error, i, j;
struct elfhdr elf_ex;
Expand All @@ -312,7 +305,7 @@ index 7c1e65d..93181d3 100644

if (memcmp(elf_ex.e_ident, ELFMAG, SELFMAG) != 0)
goto out;
@@ -1052,7 +1183,8 @@ static int load_elf_library(struct file *file)
@@ -1052,7 +1167,8 @@ static int load_elf_library(struct file *file)

eppnt = elf_phdata;
error = -ENOEXEC;
Expand All @@ -322,7 +315,7 @@ index 7c1e65d..93181d3 100644
if (retval != j)
goto out_free_ph;

@@ -1074,7 +1206,7 @@ static int load_elf_library(struct file *file)
@@ -1074,7 +1190,7 @@ static int load_elf_library(struct file *file)
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
(eppnt->p_offset -
Expand All @@ -332,22 +325,24 @@ index 7c1e65d..93181d3 100644
if (error != ELF_PAGESTART(eppnt->p_vaddr))
goto out_free_ph;
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 45a937b..9deeff4 100644
index 45a937b..a81365c 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -188,6 +188,28 @@ typedef struct elf64_sym {
@@ -188,6 +188,30 @@ typedef struct elf64_sym {
} Elf64_Sym;


+/* FatELF (multiple ELF binaries in one file) support */
+#define FATELF_MAGIC (0x1F0E70FA)
+
+typedef struct fatelf_record {
+ __le16 osabi;
+ __le16 osabi_version;
+ __le16 machine;
+ __u8 word_size; /* maps to e_ident[EI_CLASS] */
+ __u8 byte_order; /* maps to e_ident[EI_DATA] */
+ __le16 machine; /* maps to e_machine */
+ __u8 osabi; /* maps to e_ident[EI_OSABI] */
+ __u8 osabi_version; /* maps to e_ident[EI_ABIVERSION] */
+ __u8 word_size; /* maps to e_ident[EI_CLASS] */
+ __u8 byte_order; /* maps to e_ident[EI_DATA] */
+ __u8 reserved0;
+ __u8 reserved1;
+ __le64 offset;
+ __le64 size;
+} fatelf_record;
Expand Down

0 comments on commit 478ac2a

Please sign in to comment.