Skip to content

Commit

Permalink
fix: Revert to mmap-ing modules in the modulefinder (#642)
Browse files Browse the repository at this point in the history
  • Loading branch information
Swatinem authored Jan 11, 2022
1 parent 3e4d3a4 commit c5c31e5
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 4 deletions.
91 changes: 87 additions & 4 deletions src/modulefinder/sentry_modulefinder_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include <elf.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/uio.h>
Expand Down Expand Up @@ -41,6 +43,50 @@ static sentry_value_t g_modules = { 0 };

static sentry_slice_t LINUX_GATE = { "linux-gate.so", 13 };

bool
sentry__mmap_file(sentry_mmap_t *rv, const char *path)
{
int fd = open(path, O_RDONLY);
if (fd < 0) {
goto fail;
}

struct stat sb;
if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) {
goto fail;
}

rv->len = sb.st_size;
if (rv->len == 0) {
goto fail;
}

rv->ptr = mmap(NULL, rv->len, PROT_READ, MAP_PRIVATE, fd, 0);
if (rv->ptr == MAP_FAILED) {
goto fail;
}

close(fd);

return true;

fail:
if (fd > 0) {
close(fd);
}
rv->ptr = NULL;
rv->len = 0;
return false;
}

void
sentry__mmap_close(sentry_mmap_t *m)
{
munmap(m->ptr, m->len);
m->ptr = NULL;
m->len = 0;
}

/**
* Checks that `start_offset` + `size` is a valid contiguous mapping in the
* mapped regions, and returns the translated pointer corresponding to
Expand Down Expand Up @@ -112,6 +158,10 @@ sentry__module_read_safely(void *dst, const sentry_module_t *module,
if (!src) {
return false;
}
if (module->is_mmapped) {
memcpy(dst, src, (size_t)size);
return true;
}
return read_safely(dst, src, (size_t)size);
}

Expand Down Expand Up @@ -422,13 +472,46 @@ sentry__procmaps_module_to_value(const sentry_module_t *module)
const sentry_mapped_region_t *first_mapping = &module->mappings[0];
const sentry_mapped_region_t *last_mapping
= &module->mappings[module->num_mappings - 1];
uint64_t module_size
= last_mapping->addr + last_mapping->size - first_mapping->addr;

sentry_value_set_by_key(
mod_val, "image_addr", sentry__value_new_addr(first_mapping->addr));
sentry_value_set_by_key(mod_val, "image_size",
sentry_value_new_int32(
last_mapping->addr + last_mapping->size - first_mapping->addr));
sentry_value_set_by_key(
mod_val, "image_size", sentry_value_new_int32(module_size));

// At least on the android API-16, x86 simulator, the linker apparently
// does not load the complete file into memory. Or at least, the section
// headers which are located at the end of the file are not loaded, and
// we would be poking into invalid memory. To be safe, we mmap the
// complete file from disk, so we have the on-disk layout, and are
// independent of how the runtime linker would load or re-order any
// sections. The exception here is the linux-gate, which is not an
// actual file on disk, so we actually poke at its memory.
if (sentry__slice_eq(module->file, LINUX_GATE)) {
sentry__procmaps_read_ids_from_elf(mod_val, module);
} else {
char *filename = sentry__slice_to_owned(module->file);
sentry_mmap_t mm;
if (!sentry__mmap_file(&mm, filename)) {
sentry_free(filename);
sentry_value_decref(mod_val);
return sentry_value_new_null();
}
sentry_free(filename);

sentry__procmaps_read_ids_from_elf(mod_val, module);
sentry_module_t mmapped_module;
memset(&mmapped_module, 0, sizeof(sentry_module_t));
mmapped_module.is_mmapped = true;
mmapped_module.num_mappings = 1;
mmapped_module.mappings[0].addr
= (uint64_t)mm.ptr + module->offset_in_inode;
mmapped_module.mappings[0].size = mm.len - module->offset_in_inode;

sentry__procmaps_read_ids_from_elf(mod_val, &mmapped_module);

sentry__mmap_close(&mm);
}

return mod_val;
}
Expand Down
6 changes: 6 additions & 0 deletions src/modulefinder/sentry_modulefinder_linux.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ typedef struct {
uint64_t offset_in_inode;
uint64_t mappings_inode;
uint8_t num_mappings;
bool is_mmapped;
} sentry_module_t;

typedef struct {
void *ptr;
size_t len;
} sentry_mmap_t;

#ifdef SENTRY_UNITTEST
bool sentry__procmaps_read_ids_from_elf(
sentry_value_t value, const sentry_module_t *module);
Expand Down

0 comments on commit c5c31e5

Please sign in to comment.