Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 9f331c5

Browse files
kinkedlang-bot
authored andcommitted
core.internal.elf.io: Fix segfaults after mmap errors
mmap() errors lead to `TypedMMapRegion.data` being null, which previously wasn't handled and led to segfaults - while trying to resolve DWARF file/line infos for an exception backtrace. This backtrace code needs to be as resilient as possible, so give up on the first mmap error now.
1 parent 3118c7f commit 9f331c5

File tree

1 file changed

+37
-13
lines changed
  • src/core/internal/elf

1 file changed

+37
-13
lines changed

src/core/internal/elf/io.d

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,18 @@ template ElfIO(Elf_Ehdr, Elf_Shdr, ubyte ELFCLASS)
7474
*/
7575
this(int fd)
7676
{
77+
import core.stdc.stdio : SEEK_END;
78+
7779
this.fd = fd;
78-
if (fd != -1)
79-
{
80-
// memory map header
81-
this.ehdr = TypedMMapRegion!Elf_Ehdr(fd, 0);
82-
}
80+
if (fd == -1)
81+
return;
82+
83+
const fsize = lseek(fd, 0, SEEK_END);
84+
if (fsize == -1 || fsize < Elf_Ehdr.sizeof)
85+
return;
86+
87+
// okay, memory map header
88+
this.ehdr = TypedMMapRegion!Elf_Ehdr(fd, 0);
8389
}
8490

8591
@disable this(this);
@@ -98,6 +104,9 @@ template ElfIO(Elf_Ehdr, Elf_Shdr, ubyte ELFCLASS)
98104
/// Returns true if the ELF file header matches the ElfIO template parameters.
99105
bool isValid() const
100106
{
107+
if (fd == -1 || ehdr.data is null) // invalid file descriptor or mmap error
108+
return false;
109+
101110
enum EI_MAG0 = 0;
102111
enum EI_MAG1 = 1;
103112
enum EI_MAG2 = 2;
@@ -110,19 +119,13 @@ template ElfIO(Elf_Ehdr, Elf_Shdr, ubyte ELFCLASS)
110119
enum ELFMAG2 = 'L';
111120
enum ELFMAG3 = 'F';
112121

113-
enum ELFCLASS32 = 1;
114-
enum ELFCLASS64 = 2;
115-
116122
enum ELFDATA2LSB = 1;
117123
enum ELFDATA2MSB = 2;
118124

119125
version (LittleEndian) alias ELFDATA = ELFDATA2LSB;
120126
else version (BigEndian) alias ELFDATA = ELFDATA2MSB;
121127
else static assert(0, "unsupported byte order");
122128

123-
if (fd == -1)
124-
return false;
125-
126129
const ident = ehdr.e_ident;
127130

128131
if (!(ident[EI_MAG0] == ELFMAG0 &&
@@ -189,14 +192,23 @@ template ElfIO(Elf_Ehdr, Elf_Shdr, ubyte ELFCLASS)
189192
int opApply(scope Callback dg)
190193
{
191194
const stringSectionHeader = ElfSectionHeader(*file, file.ehdr.e_shstrndx);
195+
if (stringSectionHeader.shdr.data is null) // mmap error
196+
return 0;
197+
192198
const stringSection = ElfSection(*file, stringSectionHeader);
199+
const stringSectionData = cast(const char*) stringSection.data.ptr;
200+
if (stringSectionData is null) // mmap error
201+
return 0;
193202

194203
foreach (i; 0 .. file.ehdr.e_shnum)
195204
{
196205
import core.stdc.string : strlen;
197206

198207
auto sectionHeader = ElfSectionHeader(*file, i);
199-
auto sectionName = cast(const(char)*) (stringSection.data.ptr + sectionHeader.sh_name);
208+
if (sectionHeader.shdr.data is null) // mmap error
209+
return 0;
210+
211+
const sectionName = stringSectionData + sectionHeader.sh_name;
200212
const nameLen = strlen(sectionName);
201213

202214
const r = dg(i, sectionName[0 .. nameLen], move(sectionHeader));
@@ -241,7 +253,7 @@ template ElfIO(Elf_Ehdr, Elf_Shdr, ubyte ELFCLASS)
241253
this(ref const ElfFile file, ref const ElfSectionHeader shdr)
242254
{
243255
mappedRegion = TypedMMapRegion!void(file.fd, shdr.sh_offset, shdr.sh_size);
244-
size = shdr.sh_size;
256+
size = mappedRegion.data is null ? 0 : shdr.sh_size;
245257
}
246258

247259
@disable this(this);
@@ -374,3 +386,15 @@ unittest
374386
}
375387
}
376388
}
389+
390+
version (LinuxOrBSD)
391+
unittest
392+
{
393+
import core.stdc.stdio : fileno, tmpfile;
394+
395+
auto emptyFile = tmpfile();
396+
assert(emptyFile);
397+
398+
const elfFile = ElfFile(fileno(emptyFile));
399+
assert(!elfFile.isValid()); // no SIGBUS: https://issues.dlang.org/show_bug.cgi?id=21656
400+
}

0 commit comments

Comments
 (0)