Advertisement
Guest User

Untitled

a guest
Sep 6th, 2017
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.93 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 <signal.h>
  21. #include <stdarg.h>
  22. #include <stdio.h>
  23. #include <sys/prctl.h>
  24. #include <sys/time.h>
  25. #include <sys/wait.h>
  26. #include <time.h>
  27. #include <dirent.h>
  28. #include <sys/mount.h>
  29. #include <errno.h>
  30. #include <sched.h>
  31. #include <signal.h>
  32. #include <stdarg.h>
  33. #include <stdbool.h>
  34. #include <stdio.h>
  35. #include <sys/prctl.h>
  36. #include <sys/resource.h>
  37. #include <sys/time.h>
  38. #include <sys/wait.h>
  39. #include <grp.h>
  40. #include <arpa/inet.h>
  41. #include <errno.h>
  42. #include <fcntl.h>
  43. #include <linux/if.h>
  44. #include <linux/if_ether.h>
  45. #include <linux/if_tun.h>
  46. #include <linux/ip.h>
  47. #include <linux/tcp.h>
  48. #include <net/if_arp.h>
  49. #include <stdarg.h>
  50. #include <stdbool.h>
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <sys/ioctl.h>
  54. #include <sys/stat.h>
  55.  
  56. const int kFailStatus = 67;
  57. const int kRetryStatus = 69;
  58.  
  59. __attribute__((noreturn)) static void doexit(int status)
  60. {
  61. volatile unsigned i;
  62. syscall(__NR_exit_group, status);
  63. for (i = 0;; i++) {
  64. }
  65. }
  66.  
  67. __attribute__((noreturn)) static void fail(const char* msg, ...)
  68. {
  69. int e = errno;
  70. fflush(stdout);
  71. va_list args;
  72. va_start(args, msg);
  73. vfprintf(stderr, msg, args);
  74. va_end(args);
  75. fprintf(stderr, " (errno %d)\n", e);
  76. doexit((e == ENOMEM || e == EAGAIN) ? kRetryStatus : kFailStatus);
  77. }
  78.  
  79. __attribute__((noreturn)) static void exitf(const char* msg, ...)
  80. {
  81. int e = errno;
  82. fflush(stdout);
  83. va_list args;
  84. va_start(args, msg);
  85. vfprintf(stderr, msg, args);
  86. va_end(args);
  87. fprintf(stderr, " (errno %d)\n", e);
  88. doexit(kRetryStatus);
  89. }
  90.  
  91. static __thread int skip_segv;
  92. static __thread jmp_buf segv_env;
  93.  
  94. static void segv_handler(int sig, siginfo_t* info, void* uctx)
  95. {
  96. uintptr_t addr = (uintptr_t)info->si_addr;
  97. const uintptr_t prog_start = 1 << 20;
  98. const uintptr_t prog_end = 100 << 20;
  99. if (__atomic_load_n(&skip_segv, __ATOMIC_RELAXED) && (addr < prog_start || addr > prog_end)) {
  100. _longjmp(segv_env, 1);
  101. }
  102. doexit(sig);
  103. for (;;) {
  104. }
  105. }
  106.  
  107. static void install_segv_handler()
  108. {
  109. struct sigaction sa;
  110.  
  111. memset(&sa, 0, sizeof(sa));
  112. sa.sa_handler = SIG_IGN;
  113. syscall(SYS_rt_sigaction, 0x20, &sa, NULL, 8);
  114. syscall(SYS_rt_sigaction, 0x21, &sa, NULL, 8);
  115.  
  116. memset(&sa, 0, sizeof(sa));
  117. sa.sa_sigaction = segv_handler;
  118. sa.sa_flags = SA_NODEFER | SA_SIGINFO;
  119. sigaction(SIGSEGV, &sa, NULL);
  120. sigaction(SIGBUS, &sa, NULL);
  121. }
  122.  
  123. #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); }
  124.  
  125. static void use_temporary_dir()
  126. {
  127. char tmpdir_template[] = "./syzkaller.XXXXXX";
  128. char* tmpdir = mkdtemp(tmpdir_template);
  129. if (!tmpdir)
  130. fail("failed to mkdtemp");
  131. if (chmod(tmpdir, 0777))
  132. fail("failed to chmod");
  133. if (chdir(tmpdir))
  134. fail("failed to chdir");
  135. }
  136.  
  137. static void vsnprintf_check(char* str, size_t size, const char* format, va_list args)
  138. {
  139. int rv;
  140.  
  141. rv = vsnprintf(str, size, format, args);
  142. if (rv < 0)
  143. fail("tun: snprintf failed");
  144. if ((size_t)rv >= size)
  145. fail("tun: string '%s...' doesn't fit into buffer", str);
  146. }
  147.  
  148. static void snprintf_check(char* str, size_t size, const char* format, ...)
  149. {
  150. va_list args;
  151.  
  152. va_start(args, format);
  153. vsnprintf_check(str, size, format, args);
  154. va_end(args);
  155. }
  156.  
  157. #define COMMAND_MAX_LEN 128
  158.  
  159. static void execute_command(const char* format, ...)
  160. {
  161. va_list args;
  162. char command[COMMAND_MAX_LEN];
  163. int rv;
  164.  
  165. va_start(args, format);
  166.  
  167. vsnprintf_check(command, sizeof(command), format, args);
  168. rv = system(command);
  169. if (rv != 0)
  170. fail("tun: command \"%s\" failed with code %d", &command[0], rv);
  171.  
  172. va_end(args);
  173. }
  174.  
  175. static int tunfd = -1;
  176.  
  177. #define SYZ_TUN_MAX_PACKET_SIZE 1000
  178.  
  179. #define MAX_PIDS 32
  180. #define ADDR_MAX_LEN 32
  181.  
  182. #define LOCAL_MAC "aa:aa:aa:aa:aa:%02hx"
  183. #define REMOTE_MAC "bb:bb:bb:bb:bb:%02hx"
  184.  
  185. #define LOCAL_IPV4 "172.20.%d.170"
  186. #define REMOTE_IPV4 "172.20.%d.187"
  187.  
  188. #define LOCAL_IPV6 "fe80::%02hxaa"
  189. #define REMOTE_IPV6 "fe80::%02hxbb"
  190.  
  191. static void initialize_tun(uint64_t pid)
  192. {
  193. if (pid >= MAX_PIDS)
  194. fail("tun: no more than %d executors", MAX_PIDS);
  195. int id = pid;
  196.  
  197. tunfd = open("/dev/net/tun", O_RDWR | O_NONBLOCK);
  198. if (tunfd == -1)
  199. fail("tun: can't open /dev/net/tun");
  200.  
  201. char iface[IFNAMSIZ];
  202. snprintf_check(iface, sizeof(iface), "syz%d", id);
  203.  
  204. struct ifreq ifr;
  205. memset(&ifr, 0, sizeof(ifr));
  206. strncpy(ifr.ifr_name, iface, IFNAMSIZ);
  207. ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
  208. if (ioctl(tunfd, TUNSETIFF, (void*)&ifr) < 0)
  209. fail("tun: ioctl(TUNSETIFF) failed");
  210.  
  211. char local_mac[ADDR_MAX_LEN];
  212. snprintf_check(local_mac, sizeof(local_mac), LOCAL_MAC, id);
  213. char remote_mac[ADDR_MAX_LEN];
  214. snprintf_check(remote_mac, sizeof(remote_mac), REMOTE_MAC, id);
  215.  
  216. char local_ipv4[ADDR_MAX_LEN];
  217. snprintf_check(local_ipv4, sizeof(local_ipv4), LOCAL_IPV4, id);
  218. char remote_ipv4[ADDR_MAX_LEN];
  219. snprintf_check(remote_ipv4, sizeof(remote_ipv4), REMOTE_IPV4, id);
  220.  
  221. char local_ipv6[ADDR_MAX_LEN];
  222. snprintf_check(local_ipv6, sizeof(local_ipv6), LOCAL_IPV6, id);
  223. char remote_ipv6[ADDR_MAX_LEN];
  224. snprintf_check(remote_ipv6, sizeof(remote_ipv6), REMOTE_IPV6, id);
  225.  
  226. execute_command("sysctl -w net.ipv6.conf.%s.accept_dad=0", iface);
  227.  
  228. execute_command("sysctl -w net.ipv6.conf.%s.router_solicitations=0", iface);
  229.  
  230. execute_command("ip link set dev %s address %s", iface, local_mac);
  231. execute_command("ip addr add %s/24 dev %s", local_ipv4, iface);
  232. execute_command("ip -6 addr add %s/120 dev %s", local_ipv6, iface);
  233. execute_command("ip neigh add %s lladdr %s dev %s nud permanent", remote_ipv4, remote_mac, iface);
  234. execute_command("ip -6 neigh add %s lladdr %s dev %s nud permanent", remote_ipv6, remote_mac, iface);
  235. execute_command("ip link set dev %s up", iface);
  236. }
  237.  
  238. static void setup_tun(uint64_t pid, bool enable_tun)
  239. {
  240. if (enable_tun)
  241. initialize_tun(pid);
  242. }
  243.  
  244. static int read_tun(char* data, int size)
  245. {
  246. int rv = read(tunfd, data, size);
  247. if (rv < 0) {
  248. if (errno == EAGAIN)
  249. return -1;
  250. fail("tun: read failed with %d, errno: %d", rv, errno);
  251. }
  252. return rv;
  253. }
  254.  
  255. static void flush_tun()
  256. {
  257. char data[SYZ_TUN_MAX_PACKET_SIZE];
  258. while (read_tun(&data[0], sizeof(data)) != -1)
  259. ;
  260. }
  261.  
  262. static void loop();
  263.  
  264. static void sandbox_common()
  265. {
  266. prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
  267. setpgrp();
  268. setsid();
  269.  
  270. struct rlimit rlim;
  271. rlim.rlim_cur = rlim.rlim_max = 128 << 20;
  272. setrlimit(RLIMIT_AS, &rlim);
  273. rlim.rlim_cur = rlim.rlim_max = 8 << 20;
  274. setrlimit(RLIMIT_MEMLOCK, &rlim);
  275. rlim.rlim_cur = rlim.rlim_max = 1 << 20;
  276. setrlimit(RLIMIT_FSIZE, &rlim);
  277. rlim.rlim_cur = rlim.rlim_max = 1 << 20;
  278. setrlimit(RLIMIT_STACK, &rlim);
  279. rlim.rlim_cur = rlim.rlim_max = 0;
  280. setrlimit(RLIMIT_CORE, &rlim);
  281.  
  282. unshare(CLONE_NEWNS);
  283. unshare(CLONE_NEWIPC);
  284. unshare(CLONE_IO);
  285. }
  286.  
  287. static int do_sandbox_setuid(int executor_pid, bool enable_tun)
  288. {
  289. int pid = fork();
  290. if (pid)
  291. return pid;
  292.  
  293. sandbox_common();
  294. setup_tun(executor_pid, enable_tun);
  295.  
  296. const int nobody = 65534;
  297. if (setgroups(0, NULL))
  298. fail("failed to setgroups");
  299. if (syscall(SYS_setresgid, nobody, nobody, nobody))
  300. fail("failed to setresgid");
  301. if (syscall(SYS_setresuid, nobody, nobody, nobody))
  302. fail("failed to setresuid");
  303.  
  304. prctl(PR_SET_DUMPABLE, 1, 0, 0, 0);
  305.  
  306. loop();
  307. doexit(1);
  308. }
  309.  
  310. static void remove_dir(const char* dir)
  311. {
  312. DIR* dp;
  313. struct dirent* ep;
  314. int iter = 0;
  315. retry:
  316. dp = opendir(dir);
  317. if (dp == NULL) {
  318. if (errno == EMFILE) {
  319. exitf("opendir(%s) failed due to NOFILE, exiting");
  320. }
  321. exitf("opendir(%s) failed", dir);
  322. }
  323. while ((ep = readdir(dp))) {
  324. if (strcmp(ep->d_name, ".") == 0 || strcmp(ep->d_name, "..") == 0)
  325. continue;
  326. char filename[FILENAME_MAX];
  327. snprintf(filename, sizeof(filename), "%s/%s", dir, ep->d_name);
  328. struct stat st;
  329. if (lstat(filename, &st))
  330. exitf("lstat(%s) failed", filename);
  331. if (S_ISDIR(st.st_mode)) {
  332. remove_dir(filename);
  333. continue;
  334. }
  335. int i;
  336. for (i = 0;; i++) {
  337. if (unlink(filename) == 0)
  338. break;
  339. if (errno == EROFS) {
  340. break;
  341. }
  342. if (errno != EBUSY || i > 100)
  343. exitf("unlink(%s) failed", filename);
  344. if (umount2(filename, MNT_DETACH))
  345. exitf("umount(%s) failed", filename);
  346. }
  347. }
  348. closedir(dp);
  349. int i;
  350. for (i = 0;; i++) {
  351. if (rmdir(dir) == 0)
  352. break;
  353. if (i < 100) {
  354. if (errno == EROFS) {
  355. break;
  356. }
  357. if (errno == EBUSY) {
  358. if (umount2(dir, MNT_DETACH))
  359. exitf("umount(%s) failed", dir);
  360. continue;
  361. }
  362. if (errno == ENOTEMPTY) {
  363. if (iter < 100) {
  364. iter++;
  365. goto retry;
  366. }
  367. }
  368. }
  369. exitf("rmdir(%s) failed", dir);
  370. }
  371. }
  372.  
  373. static uint64_t current_time_ms()
  374. {
  375. struct timespec ts;
  376.  
  377. if (clock_gettime(CLOCK_MONOTONIC, &ts))
  378. fail("clock_gettime failed");
  379. return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
  380. }
  381.  
  382. static void test();
  383.  
  384. void loop()
  385. {
  386. int iter;
  387. for (iter = 0;; iter++) {
  388. char cwdbuf[256];
  389. sprintf(cwdbuf, "./%d", iter);
  390. if (mkdir(cwdbuf, 0777))
  391. fail("failed to mkdir");
  392. int pid = fork();
  393. if (pid < 0)
  394. fail("clone failed");
  395. if (pid == 0) {
  396. prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
  397. setpgrp();
  398. if (chdir(cwdbuf))
  399. fail("failed to chdir");
  400. flush_tun();
  401. test();
  402. doexit(0);
  403. }
  404. int status = 0;
  405. uint64_t start = current_time_ms();
  406. for (;;) {
  407. int res = waitpid(-1, &status, __WALL | WNOHANG);
  408. if (res == pid)
  409. break;
  410. usleep(1000);
  411. if (current_time_ms() - start > 5 * 1000) {
  412. kill(-pid, SIGKILL);
  413. kill(pid, SIGKILL);
  414. while (waitpid(-1, &status, __WALL) != pid) {
  415. }
  416. break;
  417. }
  418. }
  419. remove_dir(cwdbuf);
  420. }
  421. }
  422.  
  423. long r[5];
  424. void *thr(void *arg)
  425. {
  426. switch ((long)arg) {
  427. case 0:
  428. NONFAILING(*(uint32_t*)0x20005000 = (uint32_t)0x0);
  429. NONFAILING(*(uint64_t*)0x20002ff0 = (uint64_t)0x0);
  430. NONFAILING(*(uint64_t*)0x20002ff8 = (uint64_t)0x0);
  431. NONFAILING(*(uint32_t*)0x20005ffc = (uint32_t)0x0);
  432. r[4] = syscall(__NR_futex, 0x20005000ul, 0x8000000000000085ul, 0x0ul, 0x20002ff0ul, 0x20005ffcul, 0xfffffffffffffffeul);
  433. break;
  434. }
  435. return 0;
  436. }
  437.  
  438. void test()
  439. {
  440. long i;
  441. pthread_t th[2];
  442.  
  443. syscall(SYS_write, 1, "executing program\n", strlen("executing program\n"));
  444. memset(r, -1, sizeof(r));
  445. for (i = 0; i < 1; i++) {
  446. pthread_create(&th[i], 0, thr, (void*)i);
  447. usleep(rand()%10000);
  448. }
  449. usleep(rand()%100000);
  450. }
  451.  
  452. int main()
  453. {
  454. int i; for (i = 0; i < 4; i++) {
  455. if (fork() == 0) {
  456. install_segv_handler();
  457. use_temporary_dir();
  458. int pid = do_sandbox_setuid(i, true);
  459. int status = 0;
  460. while (waitpid(pid, &status, __WALL) != pid) {}
  461. return 0;
  462. }
  463. }
  464. sleep(1000000);
  465. return 0;
  466. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement