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;

Reply via email to