diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 590ee2bc..a6f1039a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,7 @@ name: ci on: + workflow_dispatch: push: branches: - devel @@ -17,7 +18,7 @@ concurrency: cancel-in-progress: true jobs: - spindle-serial-ubuntu: + spindle-serial-ubuntu_x86: name: Testsuite (Serial, Ubuntu) environment: Spindle CI runs-on: ubuntu-latest @@ -60,6 +61,50 @@ jobs: run: | cd containers/spindle-serial-ubuntu docker compose down + + spindle-serial-ubuntu_arm64: + name: Testsuite (Serial, Ubuntu, arm64) + environment: Spindle CI + runs-on: ubuntu-24.04-arm + timeout-minutes: 30 + steps: + - name: Check out Spindle + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd + + - name: Setup Docker Compose + uses: docker/setup-compose-action@364cc21a5de5b1ee4a7f5f9d3fa374ce0ccde746 + with: + version: latest + + - name: Build spindle-serial-ubuntu image + id: serial-ubuntu-build + run: | + cd containers/spindle-serial-ubuntu + docker compose --progress=plain build + + - name: Bring spindle-serial-ubuntu up + id: serial-ubuntu-up + run: | + cd containers/spindle-serial-ubuntu + docker compose up -d + + - name: Verify munge works in spindle-serial-ubuntu + id: serial-ubuntu-munge + run: | + docker exec spindlenode bash -c 'munge -n | unmunge' + + - name: Run spindle-serial-ubuntu testsuite + id: serial-ubuntu-testsuite + run: | + docker exec spindlenode bash -c 'cd Spindle-build/testsuite && ./runTests' + + - name: Bring spindle-serial-ubuntu down + id: serial-ubuntu-down + if: ${{ always() }} + continue-on-error: true + run: | + cd containers/spindle-serial-ubuntu + docker compose down spindle-flux-ubuntu: name: Testsuite (Flux, Ubuntu) diff --git a/.gitignore b/.gitignore index dd50dea1..72c87827 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,5 @@ run_driver run_driver_rm preload_file_list build + +.idea/ diff --git a/src/client/auditclient/auditclient.c b/src/client/auditclient/auditclient.c index 2c94e81d..db7d5574 100644 --- a/src/client/auditclient/auditclient.c +++ b/src/client/auditclient/auditclient.c @@ -29,9 +29,9 @@ extern void restore_pathpatch(); unsigned int spindle_la_version(unsigned int version) { - (void)version; + //(void)version; patchDTV_init(); - return 1; + return version; } void spindle_la_activity (uintptr_t *cookie, unsigned int flag) diff --git a/src/client/auditclient/auditclient_aarch64.c b/src/client/auditclient/auditclient_aarch64.c index 1f1df68a..8e06058b 100644 --- a/src/client/auditclient/auditclient_aarch64.c +++ b/src/client/auditclient/auditclient_aarch64.c @@ -18,20 +18,20 @@ Place, Suite 330, Boston, MA 02111-1307 USA #define _GNU_SOURCE #endif -#include -#include "client.h" #include "auditclient.h" #include "spindle_debug.h" -Elf64_Addr la_aarch64_gnu_pltenter(Elf64_Sym *sym, unsigned int ndx, + + +/*Elf64_Addr la_aarch64_gnu_pltenter(Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, uintptr_t *defcook, La_aarch64_regs *regs, unsigned int *flags, const char *symname, - long int *framesizep) AUDIT_EXPORT; + long int *framesizep) AUDIT_EXPORT;*/ -Elf64_Addr la_aarch64_gnu_pltenter (Elf64_Sym *sym, unsigned int ndx, +Elf64_Addr la_aarch64_gnu_pltenter(Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, uintptr_t *defcook, La_aarch64_regs *regs, diff --git a/src/client/auditclient/auditclient_common.c b/src/client/auditclient/auditclient_common.c index de24d62b..b82fbb9b 100644 --- a/src/client/auditclient/auditclient_common.c +++ b/src/client/auditclient/auditclient_common.c @@ -18,13 +18,15 @@ Place, Suite 330, Boston, MA 02111-1307 USA in platform files like auditclient_x86_64.c */ -#include "client.h" #include "auditclient.h" #include "ldcs_api.h" #include "intercept.h" #include "writablegot.h" #include +#include #include +#include +#include #include static uintptr_t *firstcookie = NULL; @@ -163,3 +165,109 @@ unsigned int la_objclose (uintptr_t *cookie) return spindle_la_objclose(cookie); } +uintptr_t la_symbind64(Elf64_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) AUDIT_EXPORT; + +uintptr_t la_symbind64(Elf64_Sym *sym, unsigned int ndx, + uintptr_t *refcook, uintptr_t *defcook, + unsigned int *flags, const char *symname) +{ + (void)ndx; + (void)refcook; + (void)defcook; + updateDataBindingQueue(0); + Elf64_Addr target = client_call_binding(symname, sym->st_value); + *flags = 0; + return target; +} + +static int bind_global_relocations(struct link_map *map, Elf64_Rela *relocs, Elf64_Addr base, + unsigned long num_relocs, Elf64_Sym *symtable, + const char *strtable, int has_pltrelocs) +{ + unsigned long i; + unsigned long symidx; + Elf64_Addr symvalue, target; + Elf64_Sym *sym; + const char *symname; + Elf64_Addr *got_entry; + int made_reloc_table_writable = 0, result, error; + Elf64_Addr reloc_table_pagebase = 0; + size_t reloc_table_size = 0; + + for (i = 0; i < num_relocs; i++) { + Elf64_Rela *r = relocs+i; + if (ELF64_R_TYPE(r->r_info) != DATA_GOT_TYPE) + continue; + symidx = ELF64_R_SYM(r->r_info); + sym = symtable + symidx; + symname = strtable + sym->st_name; + symvalue = sym->st_value; + target = client_call_binding(symname, symvalue); + if (target == symvalue) + continue; + got_entry = (Elf64_Addr *) (r->r_offset + base); + if (has_pltrelocs) { + addToDataBindingQueue(map, target, got_entry); + } + else { + debug_printf2("Unusal, have to do data symbol bindings in a DSO without PLT\n"); + make_got_writable(got_entry, map); + *got_entry = target; + if (!made_reloc_table_writable) { + reloc_table_pagebase = ((Elf64_Addr) relocs) & ~((Elf64_Addr) (getpagesize()-1)); + reloc_table_size = ((num_relocs + 1) * sizeof(Elf64_Rela)) - 1 + (((Elf64_Addr) relocs) - reloc_table_pagebase); + debug_printf3("mprotect(%p, %lu, PROT_READ|PROT_WRITE|PROT_EXEC) making GOT table writiable\n", + (void *) reloc_table_pagebase, reloc_table_size); + result = mprotect((void *) reloc_table_pagebase, reloc_table_size, PROT_READ | PROT_WRITE | PROT_EXEC); + if (result == -1) { + error = errno; + err_printf("Could not mprotect for write to relocs 0x%lx +%lu: %s\n", + reloc_table_pagebase, reloc_table_size, strerror(error)); + continue; + } + made_reloc_table_writable = 1; + } + r->r_info &= ~((Elf64_Xword) 0xffffffff); + r->r_info |= 0; /* R_*_NONE is 0 on all supported architectures */ + } + } + + return 0; +} + +int do_global_bindings(struct link_map *map) +{ + Elf64_Dyn *dyn; + Elf64_Rela *rels = NULL; + unsigned long num_rels = 0; + Elf64_Sym *syms = NULL; + const char *strtable = NULL; + int has_pltrelocs = 0; + + dyn = map->l_ld; + if (!dyn) { + debug_printf2("DSO %s does not have dynamic section\n", map->l_name); + return 0; + } + for (; dyn->d_tag != DT_NULL; dyn++) { + if (dyn->d_tag == DT_SYMTAB) + syms = (Elf64_Sym *) dyn->d_un.d_ptr; + else if (dyn->d_tag == DT_STRTAB) + strtable = (char *) dyn->d_un.d_ptr; + else if (dyn->d_tag == DT_RELA) + rels = (Elf64_Rela *) dyn->d_un.d_ptr; + else if (dyn->d_tag == DT_RELASZ) + num_rels = dyn->d_un.d_val / sizeof(Elf64_Rela); + else if (dyn->d_tag == DT_JMPREL) + has_pltrelocs = 1; + } + if (!syms || !strtable || !rels || !num_rels) { + debug_printf2("DSO %s is missing sections needed for variable binding (%p %p %p %lu)\n", map->l_name, + syms, strtable, rels, num_rels); + return 0; + } + + return bind_global_relocations(map, rels, map->l_addr, num_rels, syms, strtable, has_pltrelocs); +} diff --git a/src/client/auditclient/auditclient_x86_64.c b/src/client/auditclient/auditclient_x86_64.c index 9ad39718..bbedb3bf 100644 --- a/src/client/auditclient/auditclient_x86_64.c +++ b/src/client/auditclient/auditclient_x86_64.c @@ -16,21 +16,15 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "auditclient.h" #include "spindle_debug.h" -#include "writablegot.h" -#include -#include -#include -#include - -/*Elf64_Addr la_x86_64_gnu_pltenter(Elf64_Sym *sym, unsigned int ndx, - uintptr_t *refcook, uintptr_t *defcook, - La_x86_64_regs *regs, unsigned int *flags, - const char *symname, long int *framesizep) AUDIT_EXPORT;*/ - -uintptr_t la_symbind64(Elf64_Sym *sym, unsigned int ndx, - uintptr_t *refcook, uintptr_t *defcook, - unsigned int *flags, const char *symname) AUDIT_EXPORT; +/*Elf64_Addr la_x86_64_gnu_pltenter(Elf64_Sym *sym, + unsigned int ndx, + uintptr_t *refcook, + uintptr_t *defcook, + La_x86_64_regs *regs, + unsigned int *flags, + const char *symname, + long int *framesizep) AUDIT_EXPORT;*/ Elf64_Addr la_x86_64_gnu_pltenter(Elf64_Sym *sym, unsigned int ndx, @@ -50,116 +44,3 @@ Elf64_Addr la_x86_64_gnu_pltenter(Elf64_Sym *sym, Elf64_Addr target = client_call_binding(symname, sym->st_value); return doPermanentBinding_idx(map, reloc_index, target, symname); } - -uintptr_t la_symbind64(Elf64_Sym *sym, unsigned int ndx, - uintptr_t *refcook, uintptr_t *defcook, - unsigned int *flags, const char *symname) -{ -// struct link_map *rmap = get_linkmap_from_cookie(refcook); -// struct link_map *dmap = get_linkmap_from_cookie(defcook); - (void)ndx; - (void)refcook; - (void)defcook; - updateDataBindingQueue(0); - Elf64_Addr target = client_call_binding(symname, sym->st_value); - *flags = 0; - return target; -} - -static int bind_global_relocations(struct link_map *map, Elf64_Rela *relocs, Elf64_Addr base, unsigned long num_relocs, - Elf64_Sym *symtable, const char *strtable, int has_pltrelocs) -{ - unsigned long i; - unsigned long symidx; - Elf64_Addr symvalue, target; - Elf64_Sym *sym; - const char *symname; - Elf64_Addr *got_entry; - int made_reloc_table_writable = 0, result, error; - Elf64_Addr reloc_table_pagebase = 0; - size_t reloc_table_size = 0; - - for (i = 0; i < num_relocs; i++) { - Elf64_Rela *r = relocs+i; - if (ELF64_R_TYPE(r->r_info) != R_X86_64_GLOB_DAT) - continue; - symidx = ELF64_R_SYM(r->r_info); - sym = symtable + symidx; - symname = strtable + sym->st_name; - symvalue = sym->st_value; - target = client_call_binding(symname, symvalue); - if (target == symvalue) - continue; - got_entry = (Elf64_Addr *) (r->r_offset + base); - if (has_pltrelocs) { - //Queue up any data-type symbols that need to be relocated and apply them - // when we do the function-type symbols in la_symbind64 - addToDataBindingQueue(map, target, got_entry); - } - else { - //This DSO has no function-type relocations. So we won't get a symbind callback. - //We'll do the bindings for the data-type relocations now. To prevent ld.so from - //overwriting these later, we'll also change the relocation type to make it a NULL - //operation. This has the unfortunate side effect of modifying the binary, which - //some programs may notice if they checksum themselves. It's a trade-off between - //this or messing up data-variable bindings. - //Spindle's libsymbind_g.so test triggers this. - debug_printf2("Unusal, have to do data symbol bindings in a DSO without PLT\n"); - make_got_writable(got_entry, map); - *got_entry = target; - if (!made_reloc_table_writable) { - reloc_table_pagebase = ((Elf64_Addr) relocs) & ~((Elf64_Addr) (getpagesize()-1)); - reloc_table_size = ((num_relocs + 1) * sizeof(Elf64_Rela)) - 1 + (((Elf64_Addr) relocs) - reloc_table_pagebase); - debug_printf3("mprotect(%p, %lu, PROT_READ|PROT_WRITE|PROT_EXEC) making GOT table writiable\n", (void *) reloc_table_pagebase, reloc_table_size); - result = mprotect((void *) reloc_table_pagebase, reloc_table_size, PROT_READ | PROT_WRITE | PROT_EXEC); - if (result == -1) { - error = errno; - err_printf("Could not mprotect for write to relocs 0x%lx +%lu: %s\n", - reloc_table_pagebase, reloc_table_size, strerror(error)); - continue; - } - made_reloc_table_writable = 1; - } - - r->r_info &= ~((Elf64_Xword) 0xffffffff); - r->r_info |= R_X86_64_NONE; - } - } - - return 0; -} - -int do_global_bindings(struct link_map *map) -{ - Elf64_Dyn *dyn; - Elf64_Rela *rels = NULL; - unsigned long num_rels = 0; - Elf64_Sym *syms = NULL; - const char *strtable = NULL; - int has_pltrelocs = 0; - - dyn = map->l_ld; - if (!dyn) { - debug_printf2("DSO %s does not have dynamic section\n", map->l_name); - return 0; - } - for (; dyn->d_tag != DT_NULL; dyn++) { - if (dyn->d_tag == DT_SYMTAB) - syms = (Elf64_Sym *) dyn->d_un.d_ptr; - else if (dyn->d_tag == DT_STRTAB) - strtable = (char *) dyn->d_un.d_ptr; - else if (dyn->d_tag == DT_RELA) - rels = (Elf64_Rela *) dyn->d_un.d_ptr; - else if (dyn->d_tag == DT_RELASZ) - num_rels = dyn->d_un.d_val / sizeof(Elf64_Rela); - else if (dyn->d_tag == DT_JMPREL) - has_pltrelocs = 1; - } - if (!syms || !strtable || !rels || !num_rels) { - debug_printf2("DSO %s is missing sections needed for variable binding (%p %p %p %lu)\n", map->l_name, - syms, strtable, rels, num_rels); - return 0; - } - - return bind_global_relocations(map, rels, map->l_addr, num_rels, syms, strtable, has_pltrelocs); -} diff --git a/src/client/auditclient/writablegot.c b/src/client/auditclient/writablegot.c index 8170ece3..64c7c202 100644 --- a/src/client/auditclient/writablegot.c +++ b/src/client/auditclient/writablegot.c @@ -44,18 +44,17 @@ static signed int gots_last_entry; static signed int gots_size; #define GOTS_INITIAL_SIZE 32 +#include "writablegot.h" + #if defined(arch_x86_64) #define DEFAULT_RELENTSZ 24 #define EXTRA_GOT_ENTRIES 3 -#define DATA_GOT_TYPE R_X86_64_GLOB_DAT #elif defined(arch_ppc64) || defined(arch_ppc64le) #define DEFAULT_RELENTSZ 24 #define EXTRA_GOT_ENTRIES 2 -#define DATA_GOT_TYPE R_PPC64_GLOB_DAT #elif defined(arch_aarch64) #define DEFAULT_RELENTSZ 24 #define EXTRA_GOT_ENTRIES 4 -#define DATA_GOT_TYPE R_AARCH64_GLOB_DAT #else #error Need to fill in got info #endif diff --git a/src/client/auditclient/writablegot.h b/src/client/auditclient/writablegot.h index d0a66e88..7736f4a9 100644 --- a/src/client/auditclient/writablegot.h +++ b/src/client/auditclient/writablegot.h @@ -21,7 +21,19 @@ Place, Suite 330, Boston, MA 02111-1307 USA #define _GNU_SOURCE #endif +#include "config.h" #include +#include + +#if defined(arch_x86_64) +#define DATA_GOT_TYPE R_X86_64_GLOB_DAT +#elif defined(arch_ppc64) || defined(arch_ppc64le) +#define DATA_GOT_TYPE R_PPC64_GLOB_DAT +#elif defined(arch_aarch64) +#define DATA_GOT_TYPE R_AARCH64_GLOB_DAT +#else +#error Need to define DATA_GOT_TYPE for this architecture +#endif int add_wgot_library(struct link_map *map); int rm_wgot_library(struct link_map *map); diff --git a/src/client/subaudit/subaudit.c b/src/client/subaudit/subaudit.c index 982ac7ba..1e6b8f4f 100644 --- a/src/client/subaudit/subaudit.c +++ b/src/client/subaudit/subaudit.c @@ -27,7 +27,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA unsigned int spindle_la_version(unsigned int version) { - (void)version; + //(void)version; int result; int binding_offset = 0; @@ -39,7 +39,7 @@ unsigned int spindle_la_version(unsigned int version) debug_printf3("Updating subaudit bindings with offset %d\n", binding_offset); init_plt_binding_func(binding_offset); - return 1; + return version; } static void bind_to_libc()