config(8) creates ioconf.c containing #ifndef MAXEXTRALOC #define MAXEXTRALOC 32 #endif long extraloc[MAXEXTRALOC] = { -1 }; int nextraloc = MAXEXTRALOC; int uextraloc = 0;
When uextraloc gets stored in .bss where filesz < memsz the simplistic way config(8) reads an entire elf file into memory without parsing the program headers leads to various crashes or "Not enough space to change device." if the offset for I_UEXTRALOC returned by adjust() is within the address space. Forcing uextraloc into .data via int uextraloc __attribute__ ((section(".data"))) = 0; avoids the crashes. (gdb) run -ef /tmp/bsd.rd Starting program: /usr/obj/usr.sbin/config/config -ef /tmp/bsd.rd OpenBSD 6.2-beta (RAMDISK_CD) #88: Mon Sep 11 11:01:29 MDT 2017 dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/RAMDISK_CD Enter 'help' for information ukc> change pciide* 80 pciide* at pci* dev -1 function -1 flags 0x0 change [n] y Program received signal SIGSEGV, Segmentation fault. memmove () at /usr/src/lib/libc/arch/amd64/string/memmove.S:62 62 rep (gdb) bt #0 memmove () at /usr/src/lib/libc/arch/amd64/string/memmove.S:62 #1 0x00001a0a5b911d21 in change (devno=80) at /usr/src/usr.sbin/config/ukcutil.c:428 #2 0x00001a0a5b913127 in common_dev (dev=0x7f7ffffec9c2 "pciide*", len=6, unit=0, state=2, routine=99 'c') at /usr/src/usr.sbin/config/ukcutil.c:889 #3 0x00001a0a5b914faa in Xchange (cmd=0x7f7ffffec9b0) at /usr/src/usr.sbin/config/cmd.c:124 #4 0x00001a0a5b914667 in config () at /usr/src/usr.sbin/config/ukcutil.c:1330 #5 0x00001a0a5b910624 in ukc (file=0x7f7ffffee0f4 "/tmp/bsd.rd", outfile=0x0, uflag=0, force=1) at /usr/src/usr.sbin/config/ukc.c:156 #6 0x00001a0a5b903e6f in main (argc=1, argv=0x7f7ffffedfa8) at /usr/src/usr.sbin/config/main.c:172 With the patch below to error out $ ./obj/config -ef /tmp/bsd.rd OpenBSD 6.2-beta (RAMDISK_CD) #88: Mon Sep 11 11:01:29 MDT 2017 dera...@amd64.openbsd.org:/usr/src/sys/arch/amd64/compile/RAMDISK_CD Enter 'help' for information ukc> change pciide* 80 pciide* at pci* dev -1 function -1 flags 0x0 change [n] y config: symbol 0xffffffff8189ea48 in section 5 ph 3 ELF filesz < memsz not handled $ nm /tmp/bsd.rd | fgrep ffffffff8189ea48 ffffffff8189ea48 B uextraloc $ readelf -Wa /tmp/bsd.rd | head -48 ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0xffffffff81000158 Start of program headers: 64 (bytes into file) Start of section headers: 9080584 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 5 Size of section headers: 64 (bytes) Number of section headers: 10 Section header string table index: 7 Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS ffffffff81000158 000158 335e98 00 AX 0 0 4096 [ 2] .rodata PROGBITS ffffffff81336000 336000 161f90 00 WA 0 0 16 [ 3] .openbsd.randomda PROGBITS ffffffff81498000 498000 002400 00 WA 0 0 16 [ 4] .data PROGBITS ffffffff8149b000 49b000 3b2ad8 00 WA 0 0 4096 [ 5] .bss NOBITS ffffffff8184e000 84dad8 092000 00 WA 0 0 4096 [ 6] .SUNW_ctf PROGBITS 0000000000000000 84dad8 05b3da 00 0 0 1 [ 7] .shstrtab STRTAB 0000000000000000 8a8eb2 000052 00 0 0 1 [ 8] .symtab SYMTAB 0000000000000000 8a9188 068460 18 9 1754 8 [ 9] .strtab STRTAB 0000000000000000 9115e8 044d98 00 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings) I (info), L (link order), G (group), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000000 0xffffffff81000000 0x0000000001000000 0x335ff0 0x335ff0 R E 0x100000 LOAD 0x336000 0xffffffff81336000 0x0000000001336000 0x164400 0x164400 RW 0x100000 LOAD 0x49b000 0xffffffff8149b000 0x000000000149b000 0x3b2ad8 0x3b2ad8 RW 0x100000 LOAD 0x74e000 0xffffffff8184e000 0x000000000184e000 0x000000 0x092000 RW 0x100000 OPENBSD_RANDOM 0x498000 0xffffffff81498000 0x0000000001498000 0x002400 0x002400 RW 0x10 Index: exec_elf.c =================================================================== RCS file: /cvs/src/usr.sbin/config/exec_elf.c,v retrieving revision 1.15 diff -u -p -r1.15 exec_elf.c --- exec_elf.c 3 Jun 2017 23:31:37 -0000 1.15 +++ exec_elf.c 13 Sep 2017 03:56:46 -0000 @@ -51,7 +51,7 @@ off_t elf_size; caddr_t adjust(caddr_t x) { - int i; + int i, j; Elf_Shdr *s; unsigned long y = 0; @@ -62,6 +62,14 @@ adjust(caddr_t x) continue; if (((unsigned long)x >= s[i].sh_addr) && ((unsigned long)x < (s[i].sh_addr+s[i].sh_size))) { + for (j = 0; j < elf_ex.e_phnum; j++) { + if ((elf_phdr[j].p_vaddr == s[i].sh_addr) && + (elf_phdr[j].p_memsz == s[i].sh_size) && + (elf_phdr[j].p_filesz < elf_phdr[j].p_memsz)) + errx(1, "symbol %p in section %d ph %d" + " ELF filesz < memsz not handled", + x, i, j); + } y = (unsigned long)&elf_total[(unsigned long)x - s[i].sh_addr + s[i].sh_offset]; break; Index: mkioconf.c =================================================================== RCS file: /cvs/src/usr.sbin/config/mkioconf.c,v retrieving revision 1.36 diff -u -p -r1.36 mkioconf.c --- mkioconf.c 27 Oct 2016 14:33:30 -0000 1.36 +++ mkioconf.c 13 Sep 2017 04:33:47 -0000 @@ -183,7 +183,7 @@ static long loc[%d] = {", locators.used) #endif\n\ long extraloc[MAXEXTRALOC] = { -1 };\n\ int nextraloc = MAXEXTRALOC;\n\ -int uextraloc = 0;\n") < 0); +int uextraloc __attribute__ ((section(\".data\"))) = 0;\n") < 0); } static int nlocnames, maxlocnames = 8;