jail: elf: Use 64 bit variables for elf offsets
authorHauke Mehrtens <hauke@hauke-m.de>
Mon, 1 Nov 2021 13:52:54 +0000 (14:52 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Mon, 1 Nov 2021 17:54:02 +0000 (17:54 +0000)
The members p_offset, p_filesz and p_vaddr of the structure Elf64_Phdr
are all uint64_t. This structure is used for 64 bit applications.

Without this change we would convert the 64 bit values into 32 bit
values and an overflow could happen in this conversion.

On MIPS 64 BE the variable load_vaddr has the value 0x120000000 which
sets the 32th bit which will overflow when converted to a 32 bit value.

On 32 bit systems Elf32_Phdr is used with uint32_t, converting this to
64 bit values too should not cause problems as this is not in the hot
path.

Without this fix I am getting error messages like this at bootup on MIPS 64 BE:
[   16.622602] do_page_fault(): sending SIGSEGV to ujail for invalid read access from 00000100f37251e3
[   16.622907] epc = 000000aaab4ed0e0 in ujail[aaab4e0000+18000]
[   16.623237] ra  = 000000aaab4ed694 in ujail[aaab4e0000+18000]

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
jail/elf.c

index f67515b196b4ae7af5a6007db3f366d25f8d5088..18a7b7cc6fce5ad3625e00cce8d9aa96b7548a4e 100644 (file)
@@ -102,7 +102,7 @@ const char* find_lib(const char *file)
        return l->path;
 }
 
-static int elf64_find_section(const char *map, unsigned int type, unsigned int *offset, unsigned int *size, unsigned int *vaddr)
+static int elf64_find_section(const char *map, unsigned int type, unsigned long *offset, unsigned long *size, unsigned long *vaddr)
 {
        Elf64_Ehdr *e;
        Elf64_Phdr *ph;
@@ -125,7 +125,7 @@ static int elf64_find_section(const char *map, unsigned int type, unsigned int *
        return -1;
 }
 
-static int elf32_find_section(const char *map, unsigned int type, unsigned int *offset, unsigned int *size, unsigned int *vaddr)
+static int elf32_find_section(const char *map, unsigned int type, unsigned long *offset, unsigned long *size, unsigned long *vaddr)
 {
        Elf32_Ehdr *e;
        Elf32_Phdr *ph;
@@ -148,7 +148,7 @@ static int elf32_find_section(const char *map, unsigned int type, unsigned int *
        return -1;
 }
 
-static int elf_find_section(const char *map, unsigned int type, unsigned int *offset, unsigned int *size, unsigned int *vaddr)
+static int elf_find_section(const char *map, unsigned int type, unsigned long *offset, unsigned long *size, unsigned long *vaddr)
 {
        int clazz = map[EI_CLASS];
 
@@ -162,7 +162,7 @@ static int elf_find_section(const char *map, unsigned int type, unsigned int *of
        return -1;
 }
 
-static int elf32_scan_dynamic(const char *map, int dyn_offset, int dyn_size, int load_offset)
+static int elf32_scan_dynamic(const char *map, unsigned long dyn_offset, unsigned long dyn_size, long load_offset)
 {
        Elf32_Dyn *dynamic = (Elf32_Dyn *) (map + dyn_offset);
        const char *strtab = NULL;
@@ -196,7 +196,7 @@ static int elf32_scan_dynamic(const char *map, int dyn_offset, int dyn_size, int
        return 0;
 }
 
-static int elf64_scan_dynamic(const char *map, int dyn_offset, int dyn_size, int load_offset)
+static int elf64_scan_dynamic(const char *map, unsigned long dyn_offset, unsigned long dyn_size, long load_offset)
 {
        Elf64_Dyn *dynamic = (Elf64_Dyn *) (map + dyn_offset);
        const char *strtab = NULL;
@@ -232,9 +232,9 @@ static int elf64_scan_dynamic(const char *map, int dyn_offset, int dyn_size, int
 
 int elf_load_deps(const char *path, const char *map)
 {
-       unsigned int dyn_offset, dyn_size;
-       unsigned int load_offset, load_vaddr;
-       unsigned int interp_offset;
+       unsigned long dyn_offset, dyn_size;
+       unsigned long load_offset, load_vaddr;
+       unsigned long interp_offset;
 #if defined(__mips__) && (__mips == 64)
        static int gcc_mips64_bug_work_around;