From: Ian Jackson Date: Fri, 6 Oct 2017 18:03:25 +0000 (+0100) Subject: fishdescriptor: work on python code X-Git-Tag: archive/debian/6.0.0~1^2~39 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?p=chiark-utils.git;a=commitdiff_plain;h=647580c56b3b553948ad2132220f6c7ea4233430 fishdescriptor: work on python code Still very incomplete Signed-off-by: Ian Jackson --- diff --git a/fishdescriptor/Makefile b/fishdescriptor/Makefile index f906515..e6b493a 100644 --- a/fishdescriptor/Makefile +++ b/fishdescriptor/Makefile @@ -9,6 +9,8 @@ MINOR=0 LIBCANON= libfishdescriptor-donate.so.$(MAJOR) LIBTARGET= $(LIBCANON).$(MINOR) +all: $(LIBTARGET) + $(LIBTARGET): donate.o $(CC) -shared -Wl,-soname -Wl,$(LIBCANON) -o $@ $< $(LIBS) diff --git a/fishdescriptor/greenend/fishdescriptor/__init__.py b/fishdescriptor/greenend/fishdescriptor/__init__.py new file mode 100644 index 0000000..2a80833 --- /dev/null +++ b/fishdescriptor/greenend/fishdescriptor/__init__.py @@ -0,0 +1,2 @@ + +class diff --git a/fishdescriptor/greenend/fishdescriptor/indonor.py b/fishdescriptor/greenend/fishdescriptor/indonor.py new file mode 100644 index 0000000..b9e9053 --- /dev/null +++ b/fishdescriptor/greenend/fishdescriptor/indonor.py @@ -0,0 +1,71 @@ + +# class for use inside gdb which is debugging the donor process + +import gdb + +def _string_escape_for_c(s): + if not isinstance(s, bytes): + s = s.encode('utf-8') # sigh, python 2/3 compat + out = '' + for c in bytearray(s): # gets us bytes in py2 and py3 + if c == ord('\\') or c == ord('=') or c < 32 or c > 126: + out += '\\x%02x' % c + else: + out += chr(c) + return out + +class DonorImplementation(): + def __init__(self): + # works on the current gdb.Inferior + # ideally should be reused if the same process is targetd + self._open = None + self._sym = None + + def _func(self, functype, funcname, realargs): + expr = '((%s) %s) %s' % (functype, funcname, realargs) + return gdb.parse_and_eval(expr) + + def _dlfunc(self, functype, funcname, realargs): + r = self._func(functype,funcname,realargs) + if not r: + err = self._func('char* (*)(void)', 'dlerror', '()') + if not err: + err = 'dlerror said NULL!' + else: + err = err.string() + raise RuntimeError("%s failed: %s" % (funcname, err)) + return r + + def _dlopen(self): + if self._open is not None: return + rtld_print_cmd = ['fishdescriptor','--print-rtld-now']; + rtld_now = subprocess.check_output(rtld_print_cmd).rstrip('\n') + o = self._dlfunc('void* (*)(const char*, int)', + 'dlopen', + '("libfishdescriptor-donate.so.1.0", %s)' % rtld_now) + self._open = '((void*)%s)' % o + + def _dlsym(self): + if self._sym is not None: return + self._sym = self._dlfunc('void* (*)(void*, const char*)' + 'dlsym', + '(%s, "fishdescriptor_donate")' % self._open) + + def donate(self, path, fds): + self._dlopen() + self._dlsym() + r = self._func('int (*)(const char*, const int*)', + self._sym, + '("%s", (int[%d]){ %s, -1 })' + % (_string_escape_for_c(path), + len(fds) + 1, + ', '.join(["%d" % fd for fd in fds]))) + if r: + err = self._func('char* (*)(int)', + strerror, + r) + if not err: + err = 'strerror failed' + else: + err = err.string() + raise RuntimeError("donate failed: %s" % err)