Esempio n. 1
0
/// This finalizer is called automatically as the auditor library
/// is being unmapped, but only if interception is on (aka active)
/// and only on "normal" exit as described in Interposer/exit.h.
/*static*/ void
interposed_finalize(void)
{
    if (_auditor_isActiveByRequest()) {
	pid_t pid;

	// This is a really cute trick I got from a guy named Nate Eldredge.
	// The exit status is not given to the library finalizer but we
	// need it, so what can we do? This is the answer: do a meaningless
	// fork. The child just returns so that the parent can wait for
	// it and gets its exit status. There's a slight chance that
	// the extra fork will cause non-beneficial side effects but
	// that should be quite rare.
	// IDEA Would it be better to use vfork() here? A big IDE
	// like Eclipse might have a large memory footprint and forking
	// it only to exit might be costly and/or have an OOM failure.
	// Answer, no, vfork is not allowed to return. There could be
	// an answer within posix_spawn but I haven't looked into it.
	if ((pid = fork_real()) == -1) {
	    putil_syserr(0, "fork");
	} else if (pid == 0) {
	    // The child just returns so the parent can wait for it.
	} else {
	    int wstat, status = 7;

	    if (waitpid(pid, &wstat, 0) == pid) {
		if (WIFEXITED(wstat)) {
		    status = WEXITSTATUS(wstat);
		}
	    } else {
		putil_syserr(0, "waitpid");
	    }

	    _audit_end("exit", EXITING, status);

	    // Do an explicit _exit( to abort any remaining library
	    // finalizers since they will have run in the child. I.e.
	    // any *previous* finalizers will have run in the
	    // original (now parent) copy and any *subsequent*
	    // ones will have run in the child, so continuing with
	    // exit processing here would run the latter set twice.
	    _exit_real(status);
	}
    } else if (_auditor_isActiveByDefault()) {
	_audit_end("exit", EXITING, 0);
    }

    /*
     * The cleanups below would be done by exit anyway but we try to
     * free things explicitly so that leak detectors such as valgrind
     * can more easily pinpoint real leaks. Perhaps we could have an
     * optimized "production mode" which skips the explicit cleanup.
     */
    code_fini();
    prop_fini();
    vb_fini();
}
Esempio n. 2
0
void _exit(int status) {
  static int loaded=0;
  static void (*_exit_real)(int status);

  if(!loaded) {
    _exit_real=0;
 
    _exit_real = (void (*)(int status)) 
      dlsym(RTLD_NEXT, "_exit");

    if(!dlerror()) loaded=1;
    else {
      IPMERR("Intercepting _exit(): load failed\n");
    }
  }

  if( ipm_state==STATE_ACTIVE || ipm_state==STATE_NOTACTIVE ) 
    ipm_finalize(0);


  _exit_real(status);
}