Debugging across pipes and sockets with strace

2020-02-27 139浏览

  • 1.Debugging across pipes and sockets with strace Niklas Hambüchen, FP Complete mail@nh2.me niklas@fpcomplete.com 1
  • 2.Scenario Privileged­server / unprivileged­client Server that runs restricted set of commands ( ls, dmesg) sent to it via a socket as root Client that sends argv[0] to the server and prints the output Problem ls case works fine dmesg case just hangs without output Further complication Assume this is hard to reproduce (only happens every 1000th time), so you really want to debug it on the currently hanging system, and not restart any processes. 2
  • 3.Code Command server command­server.py:#!/usr/bin/env python2 from __future__ import print_function import socket import subprocess from subprocess import PIPE serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREA serversocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR serversocket.bind(("localhost", 1234)) serversocket.listen(5) 3
  • 4.command­server.pycontinued:def run_command_for_client(command, clientsocket): if command in ["ls", "dmesg"]: p = subprocess.Popen([command], stdout=PIPE) p.wait() out = p.stdout.read()else:out = b"command not allowed\n" clientsocket.sendall(out) # Server loop whileTrue:(clientsocket, address) = serversocket.accept() command = clientsocket.recv(100).decode('utf­8') print("server gotcommand:" + command) run_command_for_client(command, clientsocket) clientsocket.close() 4
  • 5.Command client command­client.py:#!/usr/bin/env python2 from __future__ import print_function import socket import sys name = sys.argv[1] sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect(("localhost", 1234)) sock.sendall(name.encode('utf­8')) whileTrue:data = sock.recv(100) if len(data) == 0: break sys.stdout.write(data) 5
  • 6.Commandwrappers:unprivileged­ls.py #!/usr/bin/env python2 from __future__ import print_function import subprocess from subprocess import PIPE import sys p = subprocess.Popen(['./command­client.py', "ls"], stdout=PIPE) sys.stdout.write(p.communicate()[0]) unprivileged­dmesg.py (same thing with dmesg) .... p = subprocess.Popen(['./command­client.py', "dmesg"], ... 6
  • 7.Program communication ./unprivileged­dmesg.py stdout pipe ./command­client.py TCP socket ./command­server.py stdout pipe dmesg executable 7
  • 8.Outputs % ./command­server.py server gotcommand:'>command: