DynamoRIO / DynamoRIO/dynamorio

Private loading not working on Android 9

Open
#3,543 11 comments 0 reactions 0 assignees View on GitHub
Bug-ToolFail Hotlist-Release OpSys-Android
Dominant language
C
Stars
3.2k
Forks
629
Avg merge
2d 18h
Merged PRs (30d)
30

Description

The Bionic library for Android 9 have changes from Android 6 that fails dynamorio.

Below is a small trick to get it working, but not a perfectly way.

In order to running dynamorio on android9-arm64, we change `privload_call_lib_func`
```patch
diff --git a/core/unix/loader.c b/core/unix/loader.c
index 89d5d31c..00c3519e 100644
--- a/core/unix/loader.c
+++ b/core/unix/loader.c
@@ -911,7 +911,7 @@ privload_call_lib_func(fp_t func)
*/
dummy_argv[0] = dummy_str;
dummy_argv[1] = NULL;
- func(1, dummy_argv, our_environ);
+ //func(1, dummy_argv, our_environ);
}

bool
```
Firstly, we thought programs with `init` or `init_array` would behave abnormal, but a few testcases shows that It's working perfectly. Then we thought the module load callback would behave abnormal, but it also works.

The question is, what's really happening when call init functions from dynamorio privload? What would failed if we don't call init functions from dynamorio privload?

PS. Testing with libinscount.so with patch below.
```patch
+++ b/api/samples/inscount.cpp
@@ -85,6 +85,14 @@ static dr_emit_flags_t
event_app_instruction(void *drcontext, void *tag, instrlist_t *bb, instr_t *inst,
bool for_trace, bool translating, void *user_data);

+static void
+event_module_load(void *drcontext, const module_data_t *info, bool loaded)
+{
+ const char *module_name = dr_module_preferred_name(info);
+ dr_fprintf(STDOUT, "Module Name: %s\n", module_name);
+
+}
+
DR_EXPORT void
dr_client_main(client_id_t id, int argc, const char *argv[])
{
@@ -108,6 +116,7 @@ dr_client_main(client_id_t id, int argc, const char *argv[])
dr_register_exit_event(event_exit);
drmgr_register_bb_instrumentation_event(event_bb_analysis, event_app_instruction,
NULL);
+ drmgr_register_module_load_event(event_module_load);

/* make it easy to tell, by looking at log file, which client executed */
dr_log(NULL, DR_LOG_ALL, 1, "Client 'inscount' initializing\n");
```

Testing program:

bad_case.cpp:
``` C++
// g++ bad_case.cpp -o bad_case.so -fPIC -shared
#include
#include
#include
#include
#include
#include

unsigned long global_magic;

__attribute__((constructor)) static void initall(){
global_magic = 0xdead0000;
printf("global_magic: %lx\n", global_magic);
}

__attribute__((destructor)) static void deinitall(){
global_magic = 0;
printf("global_magic: %lx\n", global_magic);
}

class BadClass{
public:
BadClass() {
this->magic_number = global_magic;
this->add_number = 0xbeef;
this->magic_number = this->magic_number + this->add_number;
}

bool isOK(){
printf("%lx\n", this->magic_number);
return this->magic_number == 0xdeadbeef;
}

~BadClass() {
printf("deconstruct\n");
this->magic_number = 0;
}

private:
unsigned long magic_number;
unsigned long add_number;
};

BadClass globalbad;
extern "C"{
int bad_case(void) {
char tmp[4096];
int cnt;
assert(globalbad.isOK());
int fd = open("/proc/self/maps", O_RDONLY);
while((cnt = read(fd, tmp, 4096)) != 0)
write(1, tmp, cnt);
return 0;
}
}
```
main.c:
```C
// gcc main.c -o main -fPIE -pie -ldl
#include
#include
int (*bad_case)(void);

int main(void){
void* handle = dlopen("./bad_case.so", RTLD_LAZY);
if(!handle) {
perror("dlopen");
exit(-1);
}
bad_case = dlsym(handle, "bad_case");
if(!bad_case) {
perror("dlsym");
exit(-1);
}

bad_case();
}
```

Contributor guide

Open the contributing guide

Research direction

Start in core/unix/loader.c at privload_call_lib_func and compare its behavior on Android 9 with the supplied workaround. Review api/samples/inscount.cpp and reproduce the loader behavior using bad_case.cpp and main.c. Done means identifying why initialization callbacks fail and defining a tested, correct handling strategy rather than relying on the workaround.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, cpp
Domain
operating-systems
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.