Skip to content

Commit

Permalink
fix: environment under pyda-attach, misc fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
ndrewh committed Nov 28, 2024
1 parent 596a5df commit e86bb80
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 6 deletions.
2 changes: 1 addition & 1 deletion bin/pyda
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash

ROOT=$(dirname "$0")/../
ASAN_OPTIONS=detect_leaks=0 LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PYTHONHOME/lib/ PYDA_SCRIPT=$1 exec $DYNAMORIO_HOME/bin64/drrun -stack_size 1024K -c $ROOT/build/pyda_core/libtool.so ${@:2}
ASAN_OPTIONS=$ASAN_OPTIONS:detect_leaks=0 LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PYTHONHOME/lib/ PYDA_SCRIPT=$1 exec $DYNAMORIO_HOME/bin64/drrun -stack_size 1024K -c $ROOT/build/pyda_core/libtool.so ${@:2}
10 changes: 8 additions & 2 deletions lib/pyda/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from pyda_core import MemoryError, ThreadExitError, InvalidStateError, FatalSignalError
from .process import Process, Map
from . import arch
import sys
import sys, os

INIT = False

Expand Down Expand Up @@ -31,4 +31,10 @@ def xinfo(addr):
path, start, end, perms = res
return Map(path=path, vaddr=start, size=end - start, perms=perms)

FatalSignalError.__str__ = lambda self: f"Signal {self.args[0]} on Thread {self.args[1]}\nBacktrace:\n{self.args[2]}"
FatalSignalError.__str__ = lambda self: f"Signal {self.args[0]} on Thread {self.args[1]}\nBacktrace:\n{self.args[2]}"

def exit(*args, **kwargs):
raise RuntimeError("exit")

os._exit = exit
sys.exit = exit
12 changes: 12 additions & 0 deletions patches/dynamorio-10.0.patch
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,18 @@ index d5133bf16..106d0672a 100644
if (ksynch_get_value(&ostd->suspended) == 0) {
/* If it still has to wait, give up the cpu. */
os_thread_yield();
diff --git a/core/unix/os_exports.h b/core/unix/os_exports.h
index c234c265c..304819704 100644
--- a/core/unix/os_exports.h
+++ b/core/unix/os_exports.h
@@ -299,6 +299,7 @@ dynamorio_set_envp(char **envp);
/* drinjectlib wants the libc version while the core wants the private version */
# define getenv our_getenv
#endif
+DR_API
char *
our_getenv(const char *name);

diff --git a/core/unix/rseq_linux.c b/core/unix/rseq_linux.c
index 4d3b9e60f..4ce713450 100644
--- a/core/unix/rseq_linux.c
Expand Down
3 changes: 2 additions & 1 deletion pyda_core/pyda_patch_python.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ static redirect_import_t python_redirect_imports[] = {
{ "pthread_detach", (app_pc)pyda_thread_detach },
{ "dlopen", (app_pc)pyda_dlopen },
{ "dlsym", (app_pc)pyda_dlsym },
{ "getauxval", (app_pc)pyda_getauxval }
{ "getauxval", (app_pc)pyda_getauxval },
{ "getenv", (app_pc)pyda_getenv }
};

#define NUM_NEW_IMPORTS (sizeof(python_redirect_imports) / sizeof(redirect_import_t))
Expand Down
48 changes: 47 additions & 1 deletion pyda_core/pyda_threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,50 @@ unsigned long pyda_getauxval(unsigned long type) {
return os_minsigstksz();
}
return getauxval(type);
}
}

int pyda_attach_mode;

extern const char *our_getenv(const char *name);
const char *pyda_getenv(const char *name) {
if (pyda_attach_mode) {
// Dynamorio does not have the correct ENV in attach mode.
DEBUG_PRINTF("getenv2 %s=%s\n", name, getenv(name));
return getenv(name);
} else {
DEBUG_PRINTF("getenv %s=%s\n", name, our_getenv(name));
return our_getenv(name);
}
}

void parse_proc_environ() {
FILE *f = fopen("/proc/self/environ", "r");
if (!f) {
DEBUG_PRINTF("Failed to open /proc/self/environ\n");
return;
}

// /proc/self/environ is a NULL-separated list of strings
// each of the form KEY=VALUE

// We store the new environment in attach_env
// and we will use that in the attach mode.

char buf[4096];
size_t len = fread(buf, 1, sizeof(buf), f);
fclose(f);

if (len == sizeof(buf)) {
DEBUG_PRINTF("Warning: /proc/self/environ too large\n");
}

char *key = buf;
while (key < buf + len) {
char *k = strtok(key, "=");
char *v = key + strlen(k) + 1;
// DEBUG_PRINTF("setenv %s=%s\n", k, v);
setenv(k, v, 0);
key = v + strlen(v) + 1;
}

}
5 changes: 4 additions & 1 deletion pyda_core/pyda_threads.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,7 @@ int pyda_thread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*st
int pyda_thread_detach(pthread_t thread);

void* python_thread_init(void *pyda_thread);
unsigned long pyda_getauxval(unsigned long type);
unsigned long pyda_getauxval(unsigned long type);
const char *pyda_getenv(const char *name);

void parse_proc_environ(void);
4 changes: 4 additions & 0 deletions pyda_core/tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ static void event_attach_post(void);


extern int is_dynamorio_running;
extern int pyda_attach_mode;

pthread_cond_t python_thread_init1;
pthread_cond_t python_thread_init2;
Expand Down Expand Up @@ -373,6 +374,9 @@ static void fork_event(void *drcontext) {
}

static void event_attach_post() {
pyda_attach_mode = 1;
parse_proc_environ();

DEBUG_PRINTF("event_attach_post on tid %d\n", dr_get_thread_id(dr_get_current_drcontext()));

pyda_thread *t = pyda_thread_getspecific(g_pyda_tls_idx);
Expand Down

0 comments on commit e86bb80

Please sign in to comment.