fuzz-wrapfd.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. #define FUZZ_SKIP_WRAP 1
  2. #include "includes.h"
  3. #include "fuzz-wrapfd.h"
  4. #include "dbutil.h"
  5. #include "fuzz.h"
  6. #define IOWRAP_MAXFD (FD_SETSIZE-1)
  7. static const int MAX_RANDOM_IN = 50000;
  8. static const double CHANCE_CLOSE = 1.0 / 600;
  9. static const double CHANCE_INTR = 1.0 / 900;
  10. static const double CHANCE_READ1 = 0.96;
  11. static const double CHANCE_READ2 = 0.5;
  12. static const double CHANCE_WRITE1 = 0.96;
  13. static const double CHANCE_WRITE2 = 0.5;
  14. struct fdwrap {
  15. enum wrapfd_mode mode;
  16. int closein;
  17. int closeout;
  18. };
  19. static struct fdwrap wrap_fds[IOWRAP_MAXFD+1] = {{UNUSED, 0, 0}};
  20. static int wrapfd_maxfd = -1;
  21. static unsigned short rand_state[3];
  22. static buffer *input_buf;
  23. static int devnull_fd = -1;
  24. static void wrapfd_remove(int fd);
  25. void wrapfd_setup(buffer *buf) {
  26. TRACE(("wrapfd_setup"))
  27. // clean old ones
  28. int i;
  29. for (i = 0; i <= wrapfd_maxfd; i++) {
  30. if (wrap_fds[i].mode != UNUSED) {
  31. wrapfd_remove(i);
  32. }
  33. }
  34. wrapfd_maxfd = -1;
  35. memset(rand_state, 0x0, sizeof(rand_state));
  36. wrapfd_setseed(50);
  37. input_buf = buf;
  38. }
  39. void wrapfd_setseed(uint32_t seed) {
  40. memcpy(rand_state, &seed, sizeof(seed));
  41. nrand48(rand_state);
  42. }
  43. int wrapfd_new_fuzzinput() {
  44. if (devnull_fd == -1) {
  45. devnull_fd = open("/dev/null", O_RDONLY);
  46. assert(devnull_fd != -1);
  47. }
  48. int fd = dup(devnull_fd);
  49. assert(fd != -1);
  50. assert(wrap_fds[fd].mode == UNUSED);
  51. wrap_fds[fd].mode = COMMONBUF;
  52. wrap_fds[fd].closein = 0;
  53. wrap_fds[fd].closeout = 0;
  54. wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
  55. return fd;
  56. }
  57. int wrapfd_new_dummy() {
  58. if (devnull_fd == -1) {
  59. devnull_fd = open("/dev/null", O_RDONLY);
  60. assert(devnull_fd != -1);
  61. }
  62. int fd = dup(devnull_fd);
  63. if (fd == -1) {
  64. return -1;
  65. }
  66. if (fd > IOWRAP_MAXFD) {
  67. close(fd);
  68. errno = EMFILE;
  69. return -1;
  70. }
  71. assert(wrap_fds[fd].mode == UNUSED);
  72. wrap_fds[fd].mode = DUMMY;
  73. wrap_fds[fd].closein = 0;
  74. wrap_fds[fd].closeout = 0;
  75. wrapfd_maxfd = MAX(fd, wrapfd_maxfd);
  76. return fd;
  77. }
  78. static void wrapfd_remove(int fd) {
  79. TRACE(("wrapfd_remove %d", fd))
  80. assert(fd >= 0);
  81. assert(fd <= IOWRAP_MAXFD);
  82. assert(wrap_fds[fd].mode != UNUSED);
  83. wrap_fds[fd].mode = UNUSED;
  84. close(fd);
  85. }
  86. int wrapfd_close(int fd) {
  87. if (fd >= 0 && fd <= IOWRAP_MAXFD && wrap_fds[fd].mode != UNUSED) {
  88. wrapfd_remove(fd);
  89. return 0;
  90. } else {
  91. return close(fd);
  92. }
  93. }
  94. int wrapfd_read(int fd, void *out, size_t count) {
  95. size_t maxread;
  96. if (!fuzz.wrapfds) {
  97. return read(fd, out, count);
  98. }
  99. if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) {
  100. /* XXX - assertion failure? */
  101. TRACE(("Bad read descriptor %d\n", fd))
  102. errno = EBADF;
  103. return -1;
  104. }
  105. assert(count != 0);
  106. if (wrap_fds[fd].closein || erand48(rand_state) < CHANCE_CLOSE) {
  107. wrap_fds[fd].closein = 1;
  108. errno = ECONNRESET;
  109. return -1;
  110. }
  111. if (erand48(rand_state) < CHANCE_INTR) {
  112. errno = EINTR;
  113. return -1;
  114. }
  115. if (input_buf && wrap_fds[fd].mode == COMMONBUF) {
  116. maxread = MIN(input_buf->len - input_buf->pos, count);
  117. /* returns 0 if buf is EOF, as intended */
  118. if (maxread > 0) {
  119. maxread = nrand48(rand_state) % maxread + 1;
  120. }
  121. memcpy(out, buf_getptr(input_buf, maxread), maxread);
  122. buf_incrpos(input_buf, maxread);
  123. return maxread;
  124. }
  125. // return fixed output, of random length
  126. maxread = MIN(MAX_RANDOM_IN, count);
  127. maxread = nrand48(rand_state) % maxread + 1;
  128. memset(out, 0xef, maxread);
  129. return maxread;
  130. }
  131. int wrapfd_write(int fd, const void* in, size_t count) {
  132. unsigned const volatile char* volin = in;
  133. unsigned int i;
  134. if (!fuzz.wrapfds) {
  135. return write(fd, in, count);
  136. }
  137. if (fd < 0 || fd > IOWRAP_MAXFD || wrap_fds[fd].mode == UNUSED) {
  138. /* XXX - assertion failure? */
  139. TRACE(("Bad read descriptor %d\n", fd))
  140. errno = EBADF;
  141. return -1;
  142. }
  143. assert(count != 0);
  144. /* force read to exercise sanitisers */
  145. for (i = 0; i < count; i++) {
  146. (void)volin[i];
  147. }
  148. if (wrap_fds[fd].closeout || erand48(rand_state) < CHANCE_CLOSE) {
  149. wrap_fds[fd].closeout = 1;
  150. errno = ECONNRESET;
  151. return -1;
  152. }
  153. if (erand48(rand_state) < CHANCE_INTR) {
  154. errno = EINTR;
  155. return -1;
  156. }
  157. return nrand48(rand_state) % (count+1);
  158. }
  159. int wrapfd_select(int nfds, fd_set *readfds, fd_set *writefds,
  160. fd_set *exceptfds, struct timeval *timeout) {
  161. int i, nset, sel;
  162. int ret = 0;
  163. int fdlist[IOWRAP_MAXFD+1];
  164. if (!fuzz.wrapfds) {
  165. return select(nfds, readfds, writefds, exceptfds, timeout);
  166. }
  167. assert(nfds <= IOWRAP_MAXFD+1);
  168. if (erand48(rand_state) < CHANCE_INTR) {
  169. errno = EINTR;
  170. return -1;
  171. }
  172. /* read */
  173. if (readfds != NULL && erand48(rand_state) < CHANCE_READ1) {
  174. for (i = 0, nset = 0; i < nfds; i++) {
  175. if (FD_ISSET(i, readfds)) {
  176. assert(wrap_fds[i].mode != UNUSED);
  177. fdlist[nset] = i;
  178. nset++;
  179. }
  180. }
  181. DROPBEAR_FD_ZERO(readfds);
  182. if (nset > 0) {
  183. /* set one */
  184. sel = fdlist[nrand48(rand_state) % nset];
  185. FD_SET(sel, readfds);
  186. ret++;
  187. if (erand48(rand_state) < CHANCE_READ2) {
  188. sel = fdlist[nrand48(rand_state) % nset];
  189. if (!FD_ISSET(sel, readfds)) {
  190. FD_SET(sel, readfds);
  191. ret++;
  192. }
  193. }
  194. }
  195. }
  196. /* write */
  197. if (writefds != NULL && erand48(rand_state) < CHANCE_WRITE1) {
  198. for (i = 0, nset = 0; i < nfds; i++) {
  199. if (FD_ISSET(i, writefds)) {
  200. assert(wrap_fds[i].mode != UNUSED);
  201. fdlist[nset] = i;
  202. nset++;
  203. }
  204. }
  205. DROPBEAR_FD_ZERO(writefds);
  206. /* set one */
  207. if (nset > 0) {
  208. sel = fdlist[nrand48(rand_state) % nset];
  209. FD_SET(sel, writefds);
  210. ret++;
  211. if (erand48(rand_state) < CHANCE_WRITE2) {
  212. sel = fdlist[nrand48(rand_state) % nset];
  213. if (!FD_ISSET(sel, writefds)) {
  214. FD_SET(sel, writefds);
  215. ret++;
  216. }
  217. }
  218. }
  219. }
  220. return ret;
  221. }
  222. int fuzz_kill(pid_t pid, int sig) {
  223. if (fuzz.fuzzing) {
  224. TRACE(("fuzz_kill ignoring pid %d signal %d", (pid), sig))
  225. if (sig >= 0) {
  226. return 0;
  227. } else {
  228. errno = EINVAL;
  229. return -1;
  230. }
  231. }
  232. return kill(pid, sig);
  233. }