Rewrite the ELF loader / harden it against bad files

This commit is contained in:
Dr. Chat
2017-05-06 23:03:45 -05:00
parent e547ec250a
commit 8bdbdcbaf0
7 changed files with 626 additions and 461 deletions

View File

@@ -10,6 +10,9 @@ modification, are permitted provided that the following conditions are met:
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY free60.org ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED

File diff suppressed because it is too large Load Diff

View File

@@ -9,9 +9,10 @@ char *argv_GetFilename(const char *argv);
char *argv_GetFilepath(const char *argv);
char *argv_GetDevice(const char *argv);
void elf_setArgcArgv(int argc, char *argv[]);
void elf_runFromMemory (void *addr, int size);
int elf_runFromDisk (char *filename);
int elf_runWithDeviceTree (void *elf_addr, int elf_size, void *dt_addr, int dt_size);
int elf_runFromMemory(void *addr, int size);
int elf_runFromDisk(char *filename);
int elf_runWithDeviceTree(void *elf_addr, int elf_size, void *dt_addr,
int dt_size);
int kernel_prepare_initrd(void *start, size_t size);
void kernel_relocate_initrd(void *start, size_t size);
void kernel_reset_initrd(void);

View File

@@ -39,6 +39,7 @@ typedef uint16_t Elf32_Half; /* Unsigned medium integer */
#define EI_MAG1 1 /* file ID */
#define EI_MAG2 2 /* file ID */
#define EI_MAG3 3 /* file ID */
#define EI_CLASS 4 /* ELF type */
#define EI_NIDENT 16 /* Size of e_ident[] */
#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
@@ -46,6 +47,10 @@ typedef uint16_t Elf32_Half; /* Unsigned medium integer */
#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
(ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
(ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
@@ -85,8 +90,33 @@ typedef struct {
Elf32_Word sh_entsize; /* section entry size */
} Elf32_Shdr;
typedef struct {
Elf32_Word p_type;
Elf32_Word p_offset;
Elf32_Word p_vaddr;
Elf32_Word p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3 /* string table section */
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8 /* no space section */
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_NOTE 4
#define SHF_ALLOC 0x2 /* occupies memory */

View File

@@ -1,49 +1,68 @@
.section ".elfldr"
#include <ppc/asm.h>
#include <ppc/xenonsprs.h>
// NOTE: All code in this file is relocated. In order to access any static data,
// you must use the offset register r2.
.globl elf_hold_thread
elf_hold_thread:
lis %r4,0x87ff
lis %r3, elf_secondary_hold_addr@h
ori %r3, %r3, elf_secondary_hold_addr@l
add %r4,%r4,%r3
// r2 = (ELF_CODE_RELOC_START - elfldr_start) (offset to reloc code)
lis %r2, 0x87f8 // This must be ELF_CODE_RELOC_START@h
lis %r3, elfldr_start@h
ori %r3, %r3, elfldr_start@l
sub %r4,%r4,%r3
sub %r2, %r2, %r3
1:
// or %r1, %r1, %r1 /* low priority */
lis %r4, elf_secondary_count@h
ori %r4, %r4, elf_secondary_count@l
/* tell the loader we're here! */
1: lwarx %r3, %r2, %r4
addi %r3, %r3, 1
stwcx. %r3, %r2, %r4
bne- 1b
lis %r3, elf_secondary_hold_addr@h
ori %r3, %r3, elf_secondary_hold_addr@l
add %r4,%r3,%r2
2:
// or %r1, %r1, %r1 /* low priority */
lwz %r3, 0(%r4)
cmpwi %r3, 0
beq 1b
beq 2b
/* Fall into elf_run. */
// or %r2, %r2, %r2
li %r4,0
.globl elf_run
elf_run:
mr %r31,%r3
mr %r30,%r4
/* Save arguments for b64 */
mr %r31,%r3 // entrypoint
mr %r30,%r4 // device tree
lis %r4,0x07ff
lis %r3, b64@h
ori %r3, %r3, b64@l
add %r4,%r4,%r3
lis %r3, elfldr_start@h
ori %r3, %r3, elfldr_start@l
sub %r4,%r4,%r3
mtsrr0 %r4
/* Load the relocated b64 routine and set it as the branch target */
lis %r4, 0x07F8 // This must be ELF_CODE_RELOC_START@h
lis %r3, b64@h
ori %r3, %r3, b64@l
add %r4,%r4,%r3
lis %r3, elfldr_start@h
ori %r3, %r3, elfldr_start@l
sub %r4,%r4,%r3
mtsrr0 %r4
/* Clear IR/DR and set 64bits mode */
/* Clear IR/DR and set 64bits mode */
mfmsr %r3
li %r4, 0x30
li %r4, 0x30
andc %r3, %r3, %r4
lis %r4, 0x8000
lis %r4, 0x8000
rldicr %r4, %r4, 32, 31
or %r3, %r3, %r4
or %r3, %r3, %r4
mtsrr1 %r3
/* Return from interrupt because we're swapping to real mode */
rfid
b64:
@@ -76,16 +95,26 @@ b64:
mfspr %r3, pir /* linux wants thread # in r3 for secondary threads */
cmplwi %r3,0
bne 1f
// We're the main thread!
mr %r3,%r30
1:
mr %r4,%r31
li %r5,0
// Kernel entry:
// r3 = DT physical pointer
// r4 = physical pointer to the kernel
// Entrypoint (from elf_run)
mtctr %r31
bctr
trap
.globl elf_secondary_hold_addr
elf_secondary_hold_addr:
.long 0
.globl elf_secondary_count
elf_secondary_count:
.long 0

View File

@@ -1,21 +1,3 @@
#include <pci/io.h>
uint32_t read32(long addr)
{
return __builtin_bswap32(*(volatile uint32_t*)addr);
}
uint32_t read32n(long addr)
{
return *(volatile uint32_t*)addr;
}
void write32(long addr, uint32_t val)
{
*(volatile uint32_t*)addr = __builtin_bswap32(val);
}
void write32n(long addr, uint32_t val)
{
*(volatile uint32_t*)addr = val;
}

View File

@@ -3,10 +3,24 @@
#include <stdint.h>
uint32_t read32(long addr);
uint32_t read32n(long addr);
static inline __attribute__((always_inline)) uint32_t read32(long addr)
{
return __builtin_bswap32(*(volatile uint32_t*)addr);
}
void write32(long addr, uint32_t val);
void write32n(long addr, uint32_t val);
static inline __attribute__((always_inline)) uint32_t read32n(long addr)
{
return *(volatile uint32_t*)addr;
}
static inline __attribute__((always_inline)) void write32(long addr, uint32_t val)
{
*(volatile uint32_t*)addr = __builtin_bswap32(val);
}
static inline __attribute__((always_inline)) void write32n(long addr, uint32_t val)
{
*(volatile uint32_t*)addr = val;
}
#endif