Skip to content

Commit

Permalink
Merge pull request #19 from 0152la/static_cleanup
Browse files Browse the repository at this point in the history
Remove static ELF binary support
  • Loading branch information
ltratt authored Feb 8, 2024
2 parents 4db7d4d + 0283343 commit adffdc5
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 adffdc5

Please sign in to comment.