def _string_escape_for_c(s):
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:
+ if c == ord('\\') or c == ord('"') or c < 32 or c > 126:
out += '\\x%02x' % c
else:
out += chr(c)
return '((%s)%s)' % (l._typename, _lit_aggregate_uncasted(build))
class DonorImplementation():
- def __init__(d):
- d._structs = { }
+ def __init__(di):
+ di._structs = { }
+ di._saved_errno = None
+ di._result_stream = os.fdopen(3, 'w')
# assembling structs
# sigh, we have to record the order of the arguments!
- def d._find_fields(typename):
+ def di._find_fields(typename):
try:
- fields = d._structs[typename]
+ fields = di._structs[typename]
except AttributeError:
fields = DonorStructLayout(typename)
- d._structs[typename] = fields
+ di._structs[typename] = fields
return fields
- def d._make(typename, values):
- fields = d._find_fields(typename)
- return fieldd.substitute(values)
+ def di._make(typename, values):
+ fields = di._find_fields(typename)
+ return fields.substitute(values)
# calling functions (need to cast the function name to the right
# type in case maybe gdb doesn't know the type)
- def _func(d, functype, funcname, realargs):
+ def _func(di, functype, funcname, realargs):
expr = '((%s) %s) %s' % (functype, funcname, realargs)
return gdb.parse_and_eval(expr)
- def _must_func(d, functype, funcname, realargs):
- retval = d._func(functype, funcname, realargs)
+ def _must_func(di, functype, funcname, realargs):
+ retval = di._func(functype, funcname, realargs)
if retval < 0:
errnoval = gdb.parse_and_eval('errno')
raise RuntimeError("%s gave errno=%d `%s'" %
- (funcname, errnoval, od.strerror(errnoval)))
+ (funcname, errnoval, os.strerror(errnoval)))
# wrappers for the syscalls that do what we want
- def _sendmsg(d, carrier, control_msg):
+ def _sendmsg(di, carrier, control_msg):
iov_base = _lit_array('int', map(str,fds))
- iov = d._make('struct iovec', {
+ iov = di._make('struct iovec', {
'iov_base': iov_base,
'iov_len' : len(fds),
})
- msg = d._make('struct msghdr', {
+ msg = di._make('struct msghdr', {
'msg_iov' : _lit_addressof(iov),
'msg_iovlen' : 1,
'msg_control' : _lit_array('char', control_msg),
'msg_controllen': len(control_msg),
})
- d._must_func(
+ di._must_func(
'ssize_t (*)(int, const struct msghdr*, int flags)',
'sendmsg',
'(%s, %s, 0)' % (carrier, _lit_addressof(msg))
)
- def _socket(d):
- return d._must_func(
+ def _socket(di):
+ return di._must_func(
'int (*)(int, int, int)',
'socket',
'(%d, %d, 0)' % (socket.AF_UNIX, socket.SOCK_STREAM)
)
- def _connect(d, fd, path):
- addr = d._make('struct sockaddr_un', {
+ def _connect(di, fd, path):
+ addr = di._make('struct sockaddr_un', {
'sun_family' : _lit_integer(socket.AF_UNIX),
'sun_path' : _lit_string_uncasted(path),
})
- d._must_func(
+ di._must_func(
'int (*)(int, const struct sockaddr*, socklen_t)',
'connect',
'(%d, (const struct sockaddr*)%s, sizeof(struct sockaddr_un))'
% (fd, _lit_addressof(addr)
)
- def _close(d, fd):
- d._must_func('int (*)(int)', 'close', '(%d)' % fd)
+ def _close(di, fd):
+ di._must_func('int (*)(int)', 'close', '(%d)' % fd)
+
+ def _mkdir(di, path, mode):
+ r = di._func(
+ 'int (*)(const char*, mode_t)',
+ 'mkdir',
+ '("%s", %d)' % (_string_escape_for_c(path), mode)
+ )
+ if r < 0:
+ errnoval = gdb.parse_and_eval('errno')
+ if errnoval != os.errno.EEXIST:
+ raise RuntimeError("mkdir %s failed: `%s'" %
+ (repr(path), os.strerror(errnoval)))
+ return 0
+ return 1
+
+ def _errno_save(di):
+ di._saved_errno = gdb.parse_and_eval('errno')
+
+ def _errno_restore(di):
+ to_restore = di._saved_errno
+ di._saved_errno = None
+ if to_restore is not None:
+ gdb.parse_and_eval('errno = %d' % to_restore))
# main entrypoints
- def donate(d, path, control_msg):
+ def result(di, output):
+ di._result_stram.write(output)
+ di._result_stram.flush()
+
+ def donate(di, path, control_msg):
# control_msg is an array of integers being the ancillary data
# array ("control") for sendmsg, and hence specifies which fds
# to pass
carrier = None
- errnoval = None
try:
- errnoval = gdb.parse_and_eval('errno')
- carrier = d._socket()
- d._connect(carrier, path)
- d._sendmsg(carrier, control_msg)
- d._close(carrier)
+ di._errno_save()
+ carrier = di._socket()
+ di._connect(carrier, path)
+ di._sendmsg(carrier, control_msg)
+ di._close(carrier)
carrier = None
finally:
if carrier is not None:
- try: d._close(carrier)
+ try: di._close(carrier)
except Exception: pass
- if errnoval is not None:
- gdb.parse_and_eval('errno = %d' % errnoval)
+ di._errno_restore()
+
+ di._result('1\n')
+
+ def geteuid(di):
+ try:
+ di._errno_save()
+ val = di._must_func('uid_t (*)(void)', 'geteuid', '()')
+ finally:
+ di._errno_restore()
+
+ di._result('%d\n' % val)
+
+ def mkdir(di, path):
+ try:
+ di._errno_save()
+ val = di._mkdir(path, '0700')
+ finally:
+ di._errno_restore()
+
+ di._result('%d\n' % val)
+
+ def _protocol_read(di):
+ return sys.stdin.readline().rstrip('\n')
+
+ def eval_loop(di):
+ while True:
+ di._result('!\n')
+ cmd = di._protocol_read()
+ eval(cmd)