Guest User

Untitled

a guest
Sep 5th, 2017
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.32 KB | None | 0 0
  1. // autogenerated by syzkaller (http://github.com/google/syzkaller)
  2.  
  3. #define _GNU_SOURCE
  4.  
  5. #include <stdint.h>
  6. #include <string.h>
  7. #include <sys/syscall.h>
  8. #include <unistd.h>
  9. #include <pthread.h>
  10. #include <stdlib.h>
  11. #include <setjmp.h>
  12. #include <signal.h>
  13. #include <string.h>
  14. #include <errno.h>
  15. #include <stdarg.h>
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <sys/stat.h>
  19. #include <errno.h>
  20. #include <sched.h>
  21. #include <signal.h>
  22. #include <stdarg.h>
  23. #include <stdbool.h>
  24. #include <stdio.h>
  25. #include <sys/prctl.h>
  26. #include <sys/resource.h>
  27. #include <sys/time.h>
  28. #include <sys/wait.h>
  29. #include <arpa/inet.h>
  30. #include <errno.h>
  31. #include <fcntl.h>
  32. #include <linux/if.h>
  33. #include <linux/if_ether.h>
  34. #include <linux/if_tun.h>
  35. #include <linux/ip.h>
  36. #include <linux/tcp.h>
  37. #include <net/if_arp.h>
  38. #include <stdarg.h>
  39. #include <stdbool.h>
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <sys/ioctl.h>
  43. #include <sys/stat.h>
  44.  
  45. const int kFailStatus = 67;
  46. const int kRetryStatus = 69;
  47.  
  48. __attribute__((noreturn)) static void doexit(int status)
  49. {
  50. volatile unsigned i;
  51. syscall(__NR_exit_group, status);
  52. for (i = 0;; i++) {
  53. }
  54. }
  55.  
  56. __attribute__((noreturn)) static void fail(const char* msg, ...)
  57. {
  58. int e = errno;
  59. fflush(stdout);
  60. va_list args;
  61. va_start(args, msg);
  62. vfprintf(stderr, msg, args);
  63. va_end(args);
  64. fprintf(stderr, " (errno %d)\n", e);
  65. doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus);
  66. }
  67.  
  68. static __thread int skip_segv;
  69. static __thread jmp_buf segv_env;
  70.  
  71. static void segv_handler(int sig, siginfo_t* info, void* uctx)
  72. {
  73. uintptr_t addr = (uintptr_t)info->si_addr;
  74. const uintptr_t prog_start = 1 << 20;
  75. const uintptr_t prog_end = 100 << 20;
  76. if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) {
  77. _longjmp(segv_env, 1);
  78. }
  79. doexit(sig);
  80. for (;;) {
  81. }
  82. }
  83.  
  84. static void install_segv_handler()
  85. {
  86. struct sigaction sa;
  87.  
  88. memset(&sa, 0, sizeof(sa));
  89. sa.sa_handler = SIG_IGN;
  90. syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8);
  91. syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8);
  92.  
  93. memset(&sa, 0, sizeof(sa));
  94. sa.sa_sigaction = segv_handler;
  95. sa.sa_flags = SA_NODEFER | SA_SIGINFO;
  96. sigaction(SIGSEGV, &sa, NULL);
  97. sigaction(SIGBUS, &sa, NULL);
  98. }
  99.  
  100. #define NONFAILING(...) { __atomic_fetch_add(&skip_segv, 1, __ATOMIC_SEQ_CST); if (_setjmp(segv_env) == 0) { __VA_ARGS__; } __atomic_fetch_sub(&skip_segv, 1, __ATOMIC_SEQ_CST); }
  101.  
  102. static void use_temporary_dir()
  103. {
  104. char tmpdir_template[] = "./syzkaller.XXXXXX";
  105. char* tmpdir = mkdtemp(tmpdir_template);
  106. if (!tmpdir)
  107. fail("failed to mkdtemp");
  108. if (chmod(tmpdir, 0777))
  109. fail("failed to chmod");
  110. if (chdir(tmpdir))
  111. fail("failed to chdir");
  112. }
  113.  
  114. static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)
  115. {
  116. int rv;
  117.  
  118. rv = vsnprintf(str, size, format, args);
  119. if (rv < 0)
  120. fail("tun: snprintf failed");
  121. if ((size_t)rv >= size)
  122. fail("tun: string '%s...' doesn't fit into buffer", str);
  123. }
  124.  
  125. static void snprintf_check(char* str, size_t size, const char* format, ...)
  126. {
  127. va_list args;
  128.  
  129. va_start(args, format);
  130. vsnprintf_check(str, size, format, args);
  131. va_end(args);
  132. }
  133.  
  134. #define COMMAND_MAX_LEN 128
  135.  
  136. static void execute_command(const char* format, ...)
  137. {
  138. va_list args;
  139. char command[COMMAND_MAX_LEN];
  140. int rv;
  141.  
  142. va_start(args, format);
  143.  
  144. vsnprintf_check(command, sizeof(command), format, args);
  145. rv = system(command);
  146. if (rv != 0)
  147. fail("tun: command \"%s\" failed with code %d", &command[0], rv);
  148.  
  149. va_end(args);
  150. }
  151.  
  152. static int tunfd = -1;
  153.  
  154. #define SYZ_TUN_MAX_PACKET_SIZE 1000
  155.  
  156. #define MAX_PIDS 32
  157. #define ADDR_MAX_LEN 32
  158.  
  159. #define LOCAL_MAC "aa:aa:aa:aa:aa:%02hx"
  160. #define REMOTE_MAC "bb:bb:bb:bb:bb:%02hx"
  161.  
  162. #define LOCAL_IPV4 "172.20.%d.170"
  163. #define REMOTE_IPV4 "172.20.%d.187"
  164.  
  165. #define LOCAL_IPV6 "fe80::%02hxaa"
  166. #define REMOTE_IPV6 "fe80::%02hxbb"
  167.  
  168. static void initialize_tun(uint64_t pid)
  169. {
  170. if (pid >= MAX_PIDS)
  171. fail("tun: no more than %d executors", MAX_PIDS);
  172. int id = pid;
  173.  
  174. tunfd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
  175. if (tunfd == -1)
  176. fail("tun: can't open /dev/net/tun");
  177.  
  178. char iface[IFNAMSIZ];
  179. snprintf_check(iface, sizeof(iface), "syz%d", id);
  180.  
  181. struct ifreq ifr;
  182. memset(&ifr, 0, sizeof(ifr));
  183. strncpy(ifr.ifr_name, iface, IFNAMSIZ);
  184. ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
  185. if (ioctl(tunfd, TUNSETIFF, (void*)&ifr) < 0)
  186. fail("tun: ioctl(TUNSETIFF) failed");
  187.  
  188. char local_mac[ADDR_MAX_LEN];
  189. snprintf_check(local_mac, sizeof(local_mac), LOCAL_MAC, id);
  190. char remote_mac[ADDR_MAX_LEN];
  191. snprintf_check(remote_mac, sizeof(remote_mac), REMOTE_MAC, id);
  192.  
  193. char local_ipv4[ADDR_MAX_LEN];
  194. snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, id);
  195. char remote_ipv4[ADDR_MAX_LEN];
  196. snprintf_check(remote_ipv4, sizeof(remote_ipv4), REMOTE_IPV4, id);
  197.  
  198. char local_ipv6[ADDR_MAX_LEN];
  199. snprintf_check(local_ipv6, sizeof(local_ipv6), LOCAL_IPV6, id);
  200. char remote_ipv6[ADDR_MAX_LEN];
  201. snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, id);
  202.  
  203. execute_command("sysctl -w net.ipv6.conf.%s.accept_dad=0", iface);
  204.  
  205. execute_command("sysctl -w net.ipv6.conf.%s.router_solicitations=0", iface);
  206.  
  207. execute_command("ip link set dev %s address %s", iface, local_mac);
  208. execute_command("ip addr add %s/24 dev %s", local_ipv4, iface);
  209. execute_command("ip -6 addr add %s/120 dev %s", local_ipv6, iface);
  210. execute_command("ip neigh add %s lladdr %s dev %s nud permanent", remote_ipv4, remote_mac, iface);
  211. execute_command("ip -6 neigh add %s lladdr %s dev %s nud permanent", remote_ipv6, remote_mac, iface);
  212. execute_command("ip link set dev %s up", iface);
  213. }
  214.  
  215. static void setup_tun(uint64_t pid, bool enable_tun)
  216. {
  217. if (enable_tun)
  218. initialize_tun(pid);
  219. }
  220.  
  221. static void loop();
  222.  
  223. static void sandbox_common()
  224. {
  225. prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
  226. setpgrp();
  227. setsid();
  228.  
  229. struct rlimit rlim;
  230. rlim.rlim_cur = rlim.rlim_max = 128 << 20;
  231. setrlimit(RLIMIT_AS, &rlim);
  232. rlim.rlim_cur = rlim.rlim_max = 8 << 20;
  233. setrlimit(RLIMIT_MEMLOCK, &rlim);
  234. rlim.rlim_cur = rlim.rlim_max = 1 << 20;
  235. setrlimit(RLIMIT_FSIZE, &rlim);
  236. rlim.rlim_cur = rlim.rlim_max = 1 << 20;
  237. setrlimit(RLIMIT_STACK, &rlim);
  238. rlim.rlim_cur = rlim.rlim_max = 0;
  239. setrlimit(RLIMIT_CORE, &rlim);
  240.  
  241. unshare(CLONE_NEWNS);
  242. unshare(CLONE_NEWIPC);
  243. unshare(CLONE_IO);
  244. }
  245.  
  246. static int do_sandbox_none(int executor_pid, bool enable_tun)
  247. {
  248. int pid = fork();
  249. if (pid)
  250. return pid;
  251.  
  252. sandbox_common();
  253. setup_tun(executor_pid, enable_tun);
  254.  
  255. loop();
  256. doexit(1);
  257. }
  258.  
  259. long r[16];
  260. void *thr(void *arg)
  261. {
  262. switch ((long)arg) {
  263. case 0:
  264. r[0] = syscall(__NR_mmap, 0x20000000ul, 0xd000ul, 0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul);
  265. break;
  266. case 1:
  267. NONFAILING(*(uint64_t*)0x20001fb0 = (uint64_t)0x0);
  268. NONFAILING(*(uint32_t*)0x20001fb8 = (uint32_t)0x1);
  269. NONFAILING(*(uint32_t*)0x20001fbc = (uint32_t)0x0);
  270. NONFAILING(*(uint64_t*)0x20001fc0 = (uint64_t)0x20007fcd);
  271. NONFAILING(*(uint64_t*)0x20001fc8 = (uint64_t)0x20005000);
  272. r[6] = syscall(__NR_timer_create, 0x3ul, 0x20001fb0ul, 0x20000000ul);
  273. break;
  274. case 2:
  275. r[7] = syscall(__NR_clock_gettime, 0x0ul, 0x20004000ul);
  276. if (r[7] != -1)
  277. NONFAILING(r[8] = *(uint64_t*)0x20004008);
  278. break;
  279. case 3:
  280. NONFAILING(*(uint64_t*)0x20006000 = (uint64_t)0x0);
  281. NONFAILING(*(uint64_t*)0x20006008 = (uint64_t)0x0);
  282. NONFAILING(*(uint64_t*)0x20006010 = (uint64_t)0x0);
  283. NONFAILING(*(uint64_t*)0x20006018 = r[8]+10000000);
  284. r[13] = syscall(__NR_timer_settime, 0x0ul, 0x0ul, 0x20006000ul, 0x20003fe0ul);
  285. break;
  286. case 4:
  287. NONFAILING(memcpy((void*)0x20006000, "\x2f\x64\x65\x76\x2f\x61\x75\x74\x6f\x66\x73\x00", 12));
  288. r[15] = syscall(__NR_openat, 0xffffffffffffff9cul, 0x20006000ul, 0x8000ul, 0x0ul);
  289. break;
  290. }
  291. return 0;
  292. }
  293.  
  294. void loop()
  295. {
  296. long i;
  297. pthread_t th[10];
  298.  
  299. syscall(SYS_write, 1, "executing program\n", strlen("executing program\n"));
  300. memset(r, -1, sizeof(r));
  301. srand(getpid());
  302. for (i = 0; i < 5; i++) {
  303. pthread_create(&th[i], 0, thr, (void*)i);
  304. usleep(rand()%10000);
  305. }
  306. for (i = 0; i < 5; i++) {
  307. pthread_create(&th[5+i], 0, thr, (void*)i);
  308. if (rand()%2)
  309. usleep(rand()%10000);
  310. }
  311. usleep(rand()%100000);
  312. }
  313.  
  314. int main()
  315. {
  316. install_segv_handler();
  317. use_temporary_dir();
  318. int pid = do_sandbox_none(0, true);
  319. int status = 0;
  320. while (waitpid(pid, &status, __WALL) != pid) {}
  321. return 0;
  322. }
Advertisement
Add Comment
Please, Sign In to add comment