0

I have a C program as such:

//Testing for program hang
//If pass in EOF, this will cause an infinite loop
void vuln() {
    char c = getchar();
    while(c != ' '){
      putchar(c);
      c = getchar();
  }
}

int main(int argc, char **argv) { vuln(); }

Which will have an infinite loop if send in a file that has no spaces.

In a python file, I am attempting to open this process and send a string to it. The problem I am having is when attempting to get the strace output for this process. Its printing a bunch of question mark characters, even when I do not specify an input to the process. Below is my python code:

from subprocess import Popen, PIPE
import signal
import time
import os

def time_out_handler(signum, frame):
    print("Infinite loop detected. Exiting program.")
    exit()

binary = './Test/hang'
testInput = 'Test/hang.txt'
proc = Popen([binary], shell=True, stdin=PIPE)
print('Running program, pid: ', proc.pid)

# TIMEOUT APPROACH
signal.signal(signal.SIGALRM, time_out_handler)
signal.alarm(10)

with open(testInput) as f:
    text = f.read()
if not isinstance(text, bytearray):
    text = bytes(text, 'utf-8')

# COVERAGE BASED
# Send input, check for strace output
# First we fork, in the child process we send the input
newpid = os.fork()
if newpid == 0:
    print('sending input')
    proc.communicate(text)
    exit()
# In parent process we create tracing process
else:
    time.sleep(1)
    print('in parent')
    while(1):
        # Attach to the proc process
        trace = Popen(['strace -p ' + str(proc.pid)], shell=True, stdout = PIPE, stderr = PIPE)
        print('Tracing program, trace_pid: ', trace.pid, '. program_pid: ', proc.pid)   
        for line in iter(trace.stderr.readline, b''):
            print(str(line))
        trace.kill()
        print('killed')
        time.sleep(1)

The terminal output when running this program is as below:

Running program, pid:  4570
sending input
in parent
Tracing program, trace_pid:  4573 . program_pid:  4570
b'strace: Process 4570 attached\n'

Then after 10 seconds, the program exits, after running the time_out_handler function. Which means it is not running any more trace processes. Additionally, if I press any button in the terminal after the proram exits, the terminal gets filled with question mark characters, and i am unable to interrupt or stop this in anyway, the only option is to ctrl-D and close the terminal window.

I am not sure if my method to do this is correct, but can anyone tell me why this behaviour is occuring?

Edo Akse
  • 4,051
  • 2
  • 10
  • 21
Roark
  • 69
  • 6
  • I am assuming you are trying to get live output from a separate process, if so please take a look at this [thread](https://stackoverflow.com/questions/18421757/live-output-from-subprocess-command). – metatoaster Aug 05 '21 at 10:12
  • Lastly, the `hang` actually got spawned and became detached after being killed, such that it keeps running in the background, while it still having the tty opened for stdout/stderr so it will spew its garbage onto the virtual terminal you had that python process opened. – metatoaster Aug 05 '21 at 10:26
  • Im trying to get strace to attach to the running hang process. I dont want the live output from hang but the live output from strace. Im killing the trace process to re run it and get a new strace output, not the hang process. The hang process should still be running since the text in proc.communicate has no space and an EOF character. – Roark Aug 05 '21 at 10:29
  • So hang is running as 1 process: ./hang < hang.txt. Then trace, strace -p , is running as a separate process. But this trace process is not returning any syscalls, even after attaching. It doesnt get killed either. – Roark Aug 05 '21 at 10:33
  • The trace process is most certainly running, except the output isn't being read correctly due to buffering, you may need to check that thread about getting actual live output. – metatoaster Aug 05 '21 at 12:11
  • okay, how would i go about checking this? – Roark Aug 06 '21 at 02:18
  • 1
    Run `ps aux | grep strace` and `ps aux | grep hang` in a separate terminal. Also the reference thread is linked in my very first comment. – metatoaster Aug 06 '21 at 02:19
  • Looking at your program some more, I don't think you can easily write what you want in Python due to how it enforces certain buffers for `subprocess.Popen` along with the buffering of stdin/stdout/stderr. Not to mention that `proc.communicate(text)` does not actually return given the infinite wait, and that impacts `trace.stderr.readline` somehow causing it to deadlock (see [here](https://docs.python.org/3/library/subprocess.html#subprocess.Popen.stderr), readline ~= read), until it got forcibly killed resulting in whatever output that was blocked by Python to start spewing into your console. – metatoaster Aug 06 '21 at 03:31
  • More related threads [here](https://stackoverflow.com/questions/2715847/read-streaming-input-from-subprocess-communicate), [here](https://stackoverflow.com/questions/5582933/need-to-avoid-subprocess-deadlock-without-communicate), and [here](https://stackoverflow.com/questions/375427/a-non-blocking-read-on-a-subprocess-pipe-in-python). – metatoaster Aug 06 '21 at 03:33

0 Answers0