Skip to content

Commit

Permalink
Remove static ELF binary support
Browse files Browse the repository at this point in the history
Since we moved to supporting dynamic `so` ELFs, support for static ELFs
has likely been broken. For code quality, we currently remove code that
handle static ELFs, as well as intercepts that were introduced primarily
for use with static ELFs.
  • Loading branch information
0152la committed Feb 8, 2024
1 parent 4db7d4d commit 0283343
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 227 deletions.
2 changes: 0 additions & 2 deletions include/intercept.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ my_fprintf(FILE *, const char *, ...);
size_t
my_call_comp(size_t, char *, void *, size_t);
static const struct FuncIntercept to_intercept_funcs[] = {
/* vDSO funcs */
{ "time", (void *) intercepted_time },
/* Mem funcs */
{ "malloc", (void *) my_malloc },
{ "realloc", (void *) my_realloc },
Expand Down
238 changes: 88 additions & 150 deletions src/compartment.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,20 @@ comp_from_elf(char *filename, char **entry_points, size_t entry_point_count,
assert(new_comp->fd != -1);
do_pread(new_comp->fd, &comp_ehdr, sizeof(Elf64_Ehdr), 0);
new_comp->elf_type = comp_ehdr.e_type;
assert(new_comp->elf_type == ET_DYN || new_comp->elf_type == ET_EXEC);
if (new_comp->elf_type != ET_DYN)
{
errx(1, "Only supporting ELFs of type DYN (shared object files)!");
}

struct stat elf_fd_stat;
fstat(new_comp->fd, &elf_fd_stat);
// TODO re-check these
// TODO re-check if we're actually using file size anywhere; I think we're
// only using loaded-segment size
new_comp->size = elf_fd_stat.st_size;

// Read program headers
Elf64_Phdr comp_phdr;
ptrdiff_t align_size_correction;
bool first_load_header = true;
for (size_t i = 0; i < comp_ehdr.e_phnum; ++i)
{
do_pread((int) new_comp->fd, &comp_phdr, sizeof(comp_phdr),
Expand All @@ -97,51 +100,18 @@ comp_from_elf(char *filename, char **entry_points, size_t entry_point_count,
continue;
}

if (new_comp->elf_type == ET_DYN)
{
new_comp->base = new_comp_base;
}
// Compute loading address of compartment for static binary
// TODO empirically, the first `LOAD` program header seems to expect to
// be loaded at the lowest address; is this correct?
else if (first_load_header)
{
void *new_comp_base = (void *) comp_phdr.p_vaddr;
assert((uintptr_t) new_comp_base % new_comp->page_size == 0);
new_comp->base = new_comp_base;
first_load_header = false;
}
new_comp->base = new_comp_base;

// Setup mapping info for the current segment
struct SegmentMap *this_seg
= (struct SegmentMap *) malloc(sizeof(struct SegmentMap));
assert(this_seg != NULL);
if (new_comp->elf_type
== ET_DYN /*|| new_comp->elf_type == ET_EXEC*/) // TODO distinguish
// PIE exec vs
// non-PIE exec
{
void *curr_seg_base = (char *) new_comp->base + comp_phdr.p_vaddr;
this_seg->mem_bot = align_down(curr_seg_base, new_comp->page_size);
align_size_correction
= (char *) curr_seg_base - (char *) this_seg->mem_bot;
this_seg->mem_top = (char *) curr_seg_base + comp_phdr.p_memsz;
}
else if (new_comp->elf_type == ET_EXEC)
{
// TODO maybe just remove this if if we don't want to support
// static binaries anymore
assert(false);
this_seg->mem_bot
= align_down((void *) comp_phdr.p_vaddr, new_comp->page_size);
align_size_correction
= (char *) comp_phdr.p_vaddr - (char *) this_seg->mem_bot;
this_seg->mem_top = (char *) comp_phdr.p_vaddr + comp_phdr.p_memsz;
}
else
{
errx(1, "Unhandled ELF type");
}
void *curr_seg_base = (char *) new_comp->base + comp_phdr.p_vaddr;
this_seg->mem_bot = align_down(curr_seg_base, new_comp->page_size);
align_size_correction
= (char *) curr_seg_base - (char *) this_seg->mem_bot;
this_seg->mem_top = (char *) curr_seg_base + comp_phdr.p_memsz;

this_seg->offset = align_down(comp_phdr.p_offset, new_comp->page_size);
this_seg->mem_sz = comp_phdr.p_memsz + align_size_correction;
this_seg->file_sz = comp_phdr.p_filesz + align_size_correction;
Expand Down Expand Up @@ -206,87 +176,81 @@ comp_from_elf(char *filename, char **entry_points, size_t entry_point_count,
}
assert(headers_of_interest_count == found_headers);

if (new_comp->elf_type == ET_DYN)
// Traverse `.rela.plt`, so we can see which function addresses we need
// to eagerly load
Elf64_Rela *comp_rela_plt = malloc(comp_rela_plt_shdr.sh_size);
do_pread((int) new_comp->fd, comp_rela_plt, comp_rela_plt_shdr.sh_size,
comp_rela_plt_shdr.sh_offset);
size_t rela_count = comp_rela_plt_shdr.sh_size / sizeof(Elf64_Rela);

Elf64_Shdr dyn_sym_hdr;
do_pread((int) new_comp->fd, &dyn_sym_hdr, sizeof(Elf64_Shdr),
comp_ehdr.e_shoff + comp_rela_plt_shdr.sh_link * sizeof(Elf64_Shdr));
Elf64_Sym *dyn_sym_tbl = malloc(dyn_sym_hdr.sh_size);
do_pread((int) new_comp->fd, dyn_sym_tbl, dyn_sym_hdr.sh_size,
dyn_sym_hdr.sh_offset);

Elf64_Shdr dyn_str_hdr;
do_pread((int) new_comp->fd, &dyn_str_hdr, sizeof(Elf64_Shdr),
comp_ehdr.e_shoff + dyn_sym_hdr.sh_link * sizeof(Elf64_Shdr));
char *dyn_str_tbl = malloc(dyn_str_hdr.sh_size);
do_pread((int) new_comp->fd, dyn_str_tbl, dyn_str_hdr.sh_size,
dyn_str_hdr.sh_offset);

new_comp->rela_maps = calloc(rela_count, sizeof(struct CompRelaMapping));
new_comp->rela_maps_count = rela_count;

// Log symbols that will need to be relocated eagerly at maptime
Elf64_Rela curr_rela;
for (size_t j = 0; j < new_comp->rela_maps_count; ++j)
{
// Traverse `.rela.plt`, so we can see which function addresses we need
// to eagerly load
Elf64_Rela *comp_rela_plt = malloc(comp_rela_plt_shdr.sh_size);
do_pread((int) new_comp->fd, comp_rela_plt, comp_rela_plt_shdr.sh_size,
comp_rela_plt_shdr.sh_offset);
size_t rela_count = comp_rela_plt_shdr.sh_size / sizeof(Elf64_Rela);

Elf64_Shdr dyn_sym_hdr;
do_pread((int) new_comp->fd, &dyn_sym_hdr, sizeof(Elf64_Shdr),
comp_ehdr.e_shoff
+ comp_rela_plt_shdr.sh_link * sizeof(Elf64_Shdr));
Elf64_Sym *dyn_sym_tbl = malloc(dyn_sym_hdr.sh_size);
do_pread((int) new_comp->fd, dyn_sym_tbl, dyn_sym_hdr.sh_size,
dyn_sym_hdr.sh_offset);

Elf64_Shdr dyn_str_hdr;
do_pread((int) new_comp->fd, &dyn_str_hdr, sizeof(Elf64_Shdr),
comp_ehdr.e_shoff + dyn_sym_hdr.sh_link * sizeof(Elf64_Shdr));
char *dyn_str_tbl = malloc(dyn_str_hdr.sh_size);
do_pread((int) new_comp->fd, dyn_str_tbl, dyn_str_hdr.sh_size,
dyn_str_hdr.sh_offset);

new_comp->rela_maps
= calloc(rela_count, sizeof(struct CompRelaMapping));
new_comp->rela_maps_count = rela_count;

// Log symbols that will need to be relocated eagerly at maptime
Elf64_Rela curr_rela;
for (size_t j = 0; j < new_comp->rela_maps_count; ++j)
{
curr_rela = comp_rela_plt[j];
size_t curr_rela_sym_idx = ELF64_R_SYM(curr_rela.r_info);
Elf64_Sym curr_rela_sym = dyn_sym_tbl[curr_rela_sym_idx];
char *curr_rela_name
= malloc(strlen(&dyn_str_tbl[curr_rela_sym.st_name]) + 1);
strcpy(curr_rela_name, &dyn_str_tbl[curr_rela_sym.st_name]);
if (ELF64_ST_BIND(curr_rela_sym.st_info) == STB_WEAK)
{
// Do not handle weak-bind symbols
// TODO should we?
struct CompRelaMapping crm = { curr_rela_name, 0, 0 };
new_comp->rela_maps[j] = crm;
continue;
} // TODO collapse

struct CompRelaMapping crm = { curr_rela_name,
curr_rela.r_offset + (char *) new_comp->base, NULL };
curr_rela = comp_rela_plt[j];
size_t curr_rela_sym_idx = ELF64_R_SYM(curr_rela.r_info);
Elf64_Sym curr_rela_sym = dyn_sym_tbl[curr_rela_sym_idx];
char *curr_rela_name
= malloc(strlen(&dyn_str_tbl[curr_rela_sym.st_name]) + 1);
strcpy(curr_rela_name, &dyn_str_tbl[curr_rela_sym.st_name]);
if (ELF64_ST_BIND(curr_rela_sym.st_info) == STB_WEAK)
{
// Do not handle weak-bind symbols
// TODO should we?
struct CompRelaMapping crm = { curr_rela_name, 0, 0 };
new_comp->rela_maps[j] = crm;
}
free(comp_rela_plt);
free(dyn_sym_tbl);
continue;
} // TODO collapse

// Find additional library dependencies
Elf64_Dyn *comp_dyn_entries = malloc(comp_dynamic_shdr.sh_size);
do_pread((int) new_comp->fd, comp_dyn_entries,
comp_dynamic_shdr.sh_size, comp_dynamic_shdr.sh_offset);
struct CompRelaMapping crm = { curr_rela_name,
curr_rela.r_offset + (char *) new_comp->base, NULL };
new_comp->rela_maps[j] = crm;
}
free(comp_rela_plt);
free(dyn_sym_tbl);

for (size_t i = 0; i < comp_dynamic_shdr.sh_size / sizeof(Elf64_Dyn);
++i)
{
if (comp_dyn_entries[i].d_tag == DT_NEEDED)
{
struct LibDependency *new_lib_dep
= malloc(sizeof(struct LibDependency));
new_lib_dep->lib_name = malloc(
strlen(&dyn_str_tbl[comp_dyn_entries[i].d_un.d_val]) + 1);
strcpy(new_lib_dep->lib_name,
&dyn_str_tbl[comp_dyn_entries[i].d_un.d_val]);
new_comp->lib_deps_count += 1;
new_comp->lib_deps = realloc(new_comp->lib_deps,
new_comp->lib_deps_count * sizeof(struct LibDependency));
new_comp->lib_deps[new_comp->lib_deps_count - 1] = new_lib_dep;
}
}
// Find additional library dependencies
Elf64_Dyn *comp_dyn_entries = malloc(comp_dynamic_shdr.sh_size);
do_pread((int) new_comp->fd, comp_dyn_entries, comp_dynamic_shdr.sh_size,
comp_dynamic_shdr.sh_offset);

free(dyn_str_tbl);
free(comp_dyn_entries);
for (size_t i = 0; i < comp_dynamic_shdr.sh_size / sizeof(Elf64_Dyn); ++i)
{
if (comp_dyn_entries[i].d_tag == DT_NEEDED)
{
struct LibDependency *new_lib_dep
= malloc(sizeof(struct LibDependency));
new_lib_dep->lib_name = malloc(
strlen(&dyn_str_tbl[comp_dyn_entries[i].d_un.d_val]) + 1);
strcpy(new_lib_dep->lib_name,
&dyn_str_tbl[comp_dyn_entries[i].d_un.d_val]);
new_comp->lib_deps_count += 1;
new_comp->lib_deps = realloc(new_comp->lib_deps,
new_comp->lib_deps_count * sizeof(struct LibDependency));
new_comp->lib_deps[new_comp->lib_deps_count - 1] = new_lib_dep;
}
}

free(dyn_str_tbl);
free(comp_dyn_entries);

// Find library files in `COMP_LIBRARY_PATH` to fulfill dependencies
for (size_t i = 0; i < new_comp->lib_deps_count; ++i)
{
Expand Down Expand Up @@ -335,22 +299,8 @@ comp_from_elf(char *filename, char **entry_points, size_t entry_point_count,
struct CompEntryPoint *new_entry_point
= malloc(sizeof(struct CompEntryPoint));
new_entry_point->fn_name = entry_points[i];
switch (new_comp->elf_type)
{
case ET_DYN:
{
new_entry_point->fn_addr
= (char *) new_comp->base + ep_syms[i].st_value;
break;
}
case ET_EXEC:
{
new_entry_point->fn_addr = (void *) ep_syms[i].st_value;
break;
}
default:
errx(1, "Invalid ELF type");
}
new_entry_point->fn_addr
= (char *) new_comp->base + ep_syms[i].st_value;
new_comp->comp_eps[new_comp->entry_point_count] = new_entry_point;
new_comp->entry_point_count += 1;
}
Expand All @@ -361,23 +311,11 @@ comp_from_elf(char *filename, char **entry_points, size_t entry_point_count,
const char *so_plt_suffix = "@plt";
for (size_t i = 0; i < intercept_count; ++i)
{
if (new_comp->elf_type == ET_DYN)
{
size_t to_intercept_name_len
= strlen(intercepts[i]) + strlen(so_plt_suffix) + 1;
intercept_names[i] = malloc(to_intercept_name_len);
strcpy(intercept_names[i], intercepts[i]);
strcat(intercept_names[i], so_plt_suffix);
}
else if (new_comp->elf_type == ET_EXEC)
{
intercept_names[i] = malloc(strlen(intercepts[i]) + 1);
strcpy(intercept_names[i], intercepts[i]);
}
else
{
errx(1, "Invalid ELF type");
}
size_t to_intercept_name_len
= strlen(intercepts[i]) + strlen(so_plt_suffix) + 1;
intercept_names[i] = malloc(to_intercept_name_len);
strcpy(intercept_names[i], intercepts[i]);
strcat(intercept_names[i], so_plt_suffix);
}
Elf64_Sym *intercept_syms
= find_symbols((const char **) intercept_names, intercept_count, false,
Expand Down
75 changes: 0 additions & 75 deletions src/intercept.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,71 +48,6 @@ setup_intercepts()
* privlige
******************************************************************************/

time_t
intercepted_time(time_t *t)
{
return time(t);
}

/* As we are performing data compartmentalization, we must store relevant
* information for accessing an opened file within compartment memory. However,
* as we are using a bump allocator for internal memory management, we do not
* have the capability of `free`ing this memory. A future implementation of a
* better memory allocator will resolve this issue.
*/
FILE *
intercepted_fopen(const char *filename, const char *mode)
{
FILE *res = fopen(filename, mode);
assert(res != NULL);
/*struct Compartment* comp =
* manager_find_compartment_by_ddc(cheri_ddc_get()); // TODO*/
void *comp_addr = manager_register_mem_alloc(loaded_comp, sizeof(FILE));
memcpy(comp_addr, res, sizeof(FILE));
return comp_addr;
}

size_t
intercepted_fread(
void *__restrict buf, size_t size, size_t count, FILE *__restrict fp)
{
return fread(buf, size, count, fp);
}

size_t
intercepted_fwrite(
void *__restrict buf, size_t size, size_t count, FILE *__restrict fp)
{
return fwrite(buf, size, count, fp);
}

int
intercepted_fputc(int chr, FILE *stream)
{
return fputc(chr, stream);
}

int
intercepted_fclose(FILE *fp)
{
int res = fclose(fp);
assert(res == 0);
return res;
}

int
intercepted_getc(FILE *stream)
{
return getc(stream);
}

// Needed by test `lua_script`
int
intercepted___srget(FILE *stream)
{
return __srget(stream);
}

void *
my_realloc(void *ptr, size_t to_alloc)
{
Expand Down Expand Up @@ -163,16 +98,6 @@ my_free(void *ptr)
return;
}

int
my_fprintf(FILE *stream, const char *format, ...)
{
va_list va_args;
va_start(va_args, format);
int res = vfprintf(stream, format, va_args);
va_end(va_args);
return res;
}

size_t
my_call_comp(size_t comp_id, char *fn_name, void *args, size_t args_count)
{
Expand Down

0 comments on commit 0283343

Please sign in to comment.