riboseinc / retrace

retrace is a versatile security vulnerability / bug discovery tool through monitoring and modifying the behavior of compiled binaries on Linux, OpenBSD/FreeBSD/NetBSD (shared object) and macOS (dynamic library).
Other
60 stars 19 forks source link

Added spawn utility #336

Closed jjr840430 closed 6 years ago

jjr840430 commented 6 years ago

Implemented the feature #333

ronaldtse commented 6 years ago

@jjr840430 thanks for this. @erikbor 's intention is actually to have this integrated within retrace -- could the main code be put inside retrace, and the spawn script be just a simple C wrapper that includes this functionality? Thanks!

jjr840430 commented 6 years ago

@drystone Thanks for your reviews. Those make sense to me.

By the way, I have some questions for your opinions about threading per fork and waitpid. Did you look the requirements in #333?

The command file may contain the number of commands more than specified number of forks. Let me know your opinions. Thanks.

drystone commented 6 years ago

@jjr840430 I was thinking of something like (not complete or tested):

for (;;) {
  while (proc_reminaing > 0 && proc_count < max_proc_count) {
    fork_a_process();
    ++proc_count;
    --proc_remaining;
  }

  /* code here to kill long running processes */
  ...

  pid = waitpid(-1, &st, WNOHANG);
  if (pid > 0)
    if(--proc_count == 0 && proc_remaining == 0)
      break;

  sleep(1);
}

I've omitted code to terminate long running processes etc.

Even better would be to use something like timer_create() to deliver the signal to the long running process and replace waitpid with plain old wait (hence no need for sleep).

while (proc_remaining > 0 || proc_count > 0) {
  if (proc_remaining > 0 && proc_count < max_proc_count) {
    fork_a_process_with_sigkill_timer();
    ++proc_count;
    --proc_remaining;
  }
  else if (wait(NULL) > 0)
    --proc_count;
}
erikbor commented 6 years ago

@jjr840430 Looks good so far!!!

Can you make a couple of modifications please:

  1. Replace prog_name with extern char *__progname;
  2. Move the code from spawn.c into a .h file and call those functions in a small spawn.c (this is to prepare spawn to be merged into Retrace itself)
  3. Increase MAX_TIMEOUT to 3600 and change if (g_opt.timeout < 0 || g_opt.timeout > 60) { to if (g_opt.timeout < 0 || g_opt.timeout > MAX_TIMEOUT) { and turn [0 ~ 60] seconds into [0 ~ %d] seconds", MAX_TIMEOUT
  4. Change No left command to be executed at thread[#%d] to No command to be executed at thread[#%d]
  5. Change The command '%s' has killed by timeout at thread[#%d] to The command '%s' was killed (timeout at thread[#%d])
  6. Change Invalid command line '%s' at thread[#%d], to Invalid command '%s' at thread[#%d]
  7. Have an option to disable the output of spawn itself (no messages of forks/threads/commands etc.)
  8. A progress bar progess: (n / total) :)

And compilation on macOS shows this warning:

spawn.c:113:11: warning: comparison of unsigned expression < 0 is always false [-Wtautological-compare]
                if (ret < 0) {
                    ~~~ ^ ~
spawn.c:386:11: warning: incompatible integer to pointer conversion assigning to 'pthread_t' (aka 'struct _opaque_pthread_t *') from 'int' [-Wint-conversion]
                        fi->th = -1;
jjr840430 commented 6 years ago

@erikbor Can you check why retrace-github-pr-macos was failed?

erikbor commented 6 years ago

@jjr840430 there's an issue with one of the macOS Jenkins slaves. No code issues 👍

jjr840430 commented 6 years ago

Thanks! :)

ronaldtse commented 6 years ago

@erikbor since there are no further issues I'm going to merge this. Thanks @jjr840430 !