Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Revert to mmap-ing modules in the modulefinder #642

Merged
merged 2 commits into from
Jan 11, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
}

return true;

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

return rv;
}

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