Advertisement
shankarapailoor

Untitled

Jun 24th, 2018
207
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.26 KB | None | 0 0
  1. // autogenerated by syzkaller (http://github.com/google/syzkaller)
  2. #define _GNU_SOURCE
  3. #include <endian.h>
  4. #include <sys/syscall.h>
  5. #include <unistd.h>
  6. #include <linux/futex.h>
  7. #include <pthread.h>
  8. #include <stdlib.h>
  9. #include <errno.h>
  10. #include <signal.h>
  11. #include <stdarg.h>
  12. #include <stdio.h>
  13. #include <sys/time.h>
  14. #include <sys/wait.h>
  15. #include <time.h>
  16. #include <sys/prctl.h>
  17. #include <dirent.h>
  18. #include <sys/mount.h>
  19. __attribute__((noreturn)) static void doexit(int status)
  20. {
  21. volatile unsigned i;
  22. syscall(__NR_exit_group, status);
  23. for (i = 0;; i++) {
  24. }
  25. }
  26. #include <stdint.h>
  27. #include <string.h>
  28. #include <errno.h>
  29. #include <stdarg.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <sys/stat.h>
  33. case 5:
  34. const int kFailStatus = 67;
  35. const int kRetryStatus = 69;
  36.  
  37. static void fail(const char* msg, ...)
  38. {
  39. int e = errno;
  40. va_list args;
  41. va_start(args, msg);
  42. vfprintf(stderr, msg, args);
  43. va_end(args);
  44. fprintf(stderr, " (errno %d)\n", e);
  45. doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus);
  46. }
  47.  
  48. static void exitf(const char* msg, ...)
  49. {
  50. int e = errno;
  51. va_list args;
  52. va_start(args, msg);
  53. vfprintf(stderr, msg, args);
  54. va_end(args);
  55. fprintf(stderr, " (errno %d)\n", e);
  56. doexit(kRetryStatus);
  57. }
  58.  
  59. static uint64_t current_time_ms()
  60. {
  61. struct timespec ts;
  62.  
  63. if (clock_gettime(CLOCK_MONOTONIC, &ts))
  64. fail("clock_gettime failed");
  65. return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
  66. }
  67.  
  68. static void use_temporary_dir()
  69. {
  70. char tmpdir_template[] = "./syzkaller.XXXXXX";
  71. char* tmpdir = mkdtemp(tmpdir_template);
  72. if (!tmpdir)
  73. fail("failed to mkdtemp");
  74. if (chmod(tmpdir, 0777))
  75. fail("failed to chmod");
  76. if (chdir(tmpdir))
  77. fail("failed to chdir");
  78. }
  79.  
  80. static void remove_dir(const char* dir)
  81. {
  82. DIR* dp;
  83. struct dirent* ep;
  84. int iter = 0;
  85. retry:
  86. while (umount2(dir, MNT_DETACH) == 0) {
  87. }
  88. dp = opendir(dir);
  89. if (dp == NULL) {
  90. if (errno == EMFILE) {
  91. exitf("opendir(%s) failed due to NOFILE, exiting", dir);
  92. }
  93. exitf("opendir(%s) failed", dir);
  94. }
  95. while ((ep = readdir(dp))) {
  96. if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
  97. continue;
  98. char filename[FILENAME_MAX];
  99. snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
  100. struct stat st;
  101. if (lstat(filename, &st))
  102. exitf("lstat(%s) failed", filename);
  103. if (S_ISDIR(st.st_mode)) {
  104. remove_dir(filename);
  105. continue;
  106. }
  107. int i;
  108. for (i = 0;; i++) {
  109. if (unlink(filename) == 0)
  110. break;
  111. if (errno == EROFS) {
  112. break;
  113. }
  114. if (errno != EBUSY || i > 100)
  115. exitf("unlink(%s) failed", filename);
  116. if (umount2(filename, MNT_DETACH))
  117. exitf("umount(%s) failed", filename);
  118. }
  119. }
  120. closedir(dp);
  121. int i;
  122. for (i = 0;; i++) {
  123. if (rmdir(dir) == 0)
  124. break;
  125. if (i < 100) {
  126. if (errno == EROFS) {
  127. break;
  128. }
  129. if (errno == EBUSY) {
  130. if (umount2(dir, MNT_DETACH))
  131. exitf("umount(%s) failed", dir);
  132. continue;
  133. }
  134. if (errno == ENOTEMPTY) {
  135. if (iter < 100) {
  136. iter++;
  137. goto retry;
  138. }
  139. }
  140. }
  141. exitf("rmdir(%s) failed", dir);
  142. }
  143. }
  144.  
  145. static void execute_one();
  146. extern unsigned long long procid;
  147.  
  148. static void loop()
  149. {
  150. int iter;
  151. for (iter = 0;; iter++) {
  152. char cwdbuf[32];
  153. sprintf(cwdbuf, "./%d", iter);
  154. if (mkdir(cwdbuf, 0777))
  155. fail("failed to mkdir");
  156. int pid = fork();
  157. if (pid < 0)
  158. fail("clone failed");
  159. if (pid == 0) {
  160. prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
  161. setpgrp();
  162. if (chdir(cwdbuf))
  163. fail("failed to chdir");
  164. execute_one();
  165. doexit(0);
  166. }
  167.  
  168. int status = 0;
  169. uint64_t start = current_time_ms();
  170. for (;;) {
  171. int res = waitpid(-1, &status, __WALL | WNOHANG);
  172. if (res == pid) {
  173. break;
  174. }
  175. usleep(1000);
  176. if (current_time_ms() - start < 3 * 1000)
  177. continue;
  178. kill(-pid, SIGKILL);
  179. kill(pid, SIGKILL);
  180. while (waitpid(-1, &status, __WALL) != pid) {
  181. }
  182. break;
  183. }
  184. remove_dir(cwdbuf);
  185. }
  186. }
  187.  
  188. struct thread_t {
  189. int created, running, call;
  190. pthread_t th;
  191. };
  192.  
  193. static struct thread_t threads[16];
  194. static void execute_call(int call);
  195. static int running;
  196. static int collide;
  197.  
  198. static void* thr(void* arg)
  199. {
  200. struct thread_t* th = (struct thread_t*)arg;
  201. for (;;) {
  202. while (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE))
  203. syscall(SYS_futex, &th->running, FUTEX_WAIT, 0, 0);
  204. execute_call(th->call);
  205. __atomic_fetch_sub(&running, 1, __ATOMIC_RELAXED);
  206. __atomic_store_n(&th->running, 0, __ATOMIC_RELEASE);
  207. syscall(SYS_futex, &th->running, FUTEX_WAKE);
  208. }
  209. return 0;
  210. }
  211.  
  212. static void execute(int num_calls)
  213. {
  214. int call, thread;
  215. running = 0;
  216. for (call = 0; call < num_calls; call++) {
  217. for (thread = 0; thread < sizeof(threads) / sizeof(threads[0]); thread++) {
  218. struct thread_t* th = &threads[thread];
  219. if (!th->created) {
  220. th->created = 1;
  221. pthread_attr_t attr;
  222. pthread_attr_init(&attr);
  223. pthread_attr_setstacksize(&attr, 128 << 10);
  224. pthread_create(&th->th, &attr, thr, th);
  225. }
  226. if (!__atomic_load_n(&th->running, __ATOMIC_ACQUIRE)) {
  227. th->call = call;
  228. __atomic_fetch_add(&running, 1, __ATOMIC_RELAXED);
  229. __atomic_store_n(&th->running, 1, __ATOMIC_RELEASE);
  230. syscall(SYS_futex, &th->running, FUTEX_WAKE);
  231. if (collide && call % 2)
  232. break;
  233. struct timespec ts;
  234. ts.tv_sec = 0;
  235. ts.tv_nsec = 20 * 1000 * 1000;
  236. syscall(SYS_futex, &th->running, FUTEX_WAIT, 1, &ts);
  237. if (running)
  238. usleep((call == num_calls - 1) ? 10000 : 1000);
  239. break;
  240. }
  241. }
  242. }
  243. }
  244.  
  245. uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};
  246. unsigned long long procid;
  247. void execute_call(int call)
  248. {
  249. long res; switch (call) {
  250. case 0:
  251. memcpy((void*)0x20000040, "./file0", 8);
  252. res = syscall(__NR_open, 0x20000040, 0x43fd, 0xfffffffffffffffe);
  253. if (res != -1)
  254. r[0] = res;
  255. break;
  256. case 1:
  257. memcpy((void*)0x20000075, "/lib/x86_64-linux-gnu/libc.so.6", 32);
  258. res = syscall(__NR_open, 0x20000075, 0, 0);
  259. if (res != -1)
  260. r[1] = res;
  261. break;
  262. case 2:
  263. *(uint64_t*)0x20000140 = 7;
  264. syscall(__NR_fcntl, r[0], 0x40e, 0x20000140);
  265. break;
  266. case 3:
  267. syscall(__NR_close, r[1]);
  268. break;
  269. case 4:
  270. memcpy((void*)0x2000044a, "./file0", 8);
  271. syscall(__NR_open, 0x2000044a, 0x242, 0);
  272. break;
  273. case 5:
  274. syscall(__NR_mmap, 0x20000000, 0x4000, 0x40000000002, 0x11, r[1], 0);
  275. break;
  276. case 6:
  277. syscall(__NR_ftruncate, r[1], 0x1073b4);
  278. break;
  279. case 7:
  280. syscall(__NR_fcntl, -1, 9);
  281. break;
  282. case 8:
  283. *(uint64_t*)0x20000000 = 0;
  284. syscall(__NR_write, r[0], 0x20000000, 0xd996d7aa);
  285. break;
  286. }
  287. }
  288.  
  289. void execute_one()
  290. {
  291. execute(9);
  292. collide = 1;
  293. execute(9);
  294. }
  295.  
  296. int main()
  297. {
  298. syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
  299. char *cwd = get_current_dir_name();
  300. for (procid = 0; procid < 8; procid++) {
  301. if (fork() == 0) {
  302. for (;;) {
  303. if (chdir(cwd))
  304. fail("failed to chdir");
  305. use_temporary_dir();
  306. loop();
  307. }
  308. }
  309. }
  310. sleep(1000000);
  311. return 0;
  312. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement