diff --git a/Makefile b/Makefile index 3cb0f9b..e2917a6 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,8 @@ default: release #debug example: default example.elf example-%: % example.elf -debug: CFLAGS += -g -Og -fsanitize=address -debug: LDFLAGS += -g -Og -fsanitize=address +debug: CFLAGS += -g -Og #-fsanitize=address +debug: LDFLAGS += -g -Og #-fsanitize=address debug: all release: CFLAGS += -O2 -flto -ffat-lto-objects @@ -33,7 +33,7 @@ libdynso.so: dynso.o $(CC) -Wl,-soname=$@ -shared -o "$@" $^ $(CFLAGS) example.elf: dynso.c example.c - $(CC) -o "$@" $^ $(CFLAGS) $(LDFLAGS) $(LIBS) -g -Og -fsanitize=address + $(CC) -o "$@" $^ $(CFLAGS) $(LDFLAGS) $(LIBS) -g -Og #-fsanitize=address clean: $(RM) *.o *.so *.a example.elf diff --git a/dynso.c b/dynso.c index 0822d4f..4b94890 100644 --- a/dynso.c +++ b/dynso.c @@ -305,6 +305,19 @@ static enum dynso_err inject_in_scope_of(struct inject_undo_info* r, struct r_scope_elem* oldscope = vic3->l_scope[0]; struct r_scope_elem* scope = NULL; + + if ((uintptr_t)&oldscope->r_nlist < 0x1000000 || oldscope->r_nlist > 0x10000) { + // things probably broke, use offsets from an older glibc version that + // hopefully do check out. this is super hacky, be warned + // (extra "l_text_end" field shifts everything one field down) + oldscope = ((struct r_scope_elem**)vic3->l_local_scope)[0]; + + if ((uintptr_t)&oldscope->r_nlist < 0x1000000 || oldscope->r_nlist > 0x10000) { + fprintf(stderr, "[%s:%d]: WELP, THINGS BROKE BADLY. time to stare at glibc internals again to see if you can fix it. Have fun!\n", __FILE__, __LINE__); + return dynso_death; + } + } + scope = (struct r_scope_elem*)calloc(1, sizeof(*scope) + sizeof(struct link_map_priv1*)*(oldscope->r_nlist+1)); if (scope == NULL) return dynso_oom; diff --git a/dynso.h b/dynso.h index 9dabf1e..e2deda1 100644 --- a/dynso.h +++ b/dynso.h @@ -27,6 +27,7 @@ enum dynso_err { dynso_no_newobj, // can't create a new symbol dynso_no_priv2, // can't find the offset of the priv2 part of a struct link_map dynso_no_priv3, // can't find the offset of the priv3 part of a struct link_map + dynso_death, // too many changes in glibc versioning }; // create a library diff --git a/dynso_internal.h b/dynso_internal.h index 164e893..8133bef 100644 --- a/dynso_internal.h +++ b/dynso_internal.h @@ -75,6 +75,7 @@ struct link_map_priv2 { lt_library, lt_loaded } l_type : 2; + // NOTE: extra bitfields seem to get added relatively commonly. just don't use them I guess unsigned int l_relocated : 1; unsigned int l_init_called : 1; unsigned int l_global : 1; @@ -121,7 +122,7 @@ struct link_map_priv3 { ElfW(Versym)* l_versyms; const char* l_origin; ElfW(Addr) l_map_start, l_map_end; - ElfW(Addr) l_text_end; + //ElfW(Addr) l_text_end; // NOTE: got removed in. 2.39? maybe?? struct r_scope_elem* l_scope_mem[4]; size_t l_scope_max; struct r_scope_elem** l_scope;