ssize_t NEW(aio_return)(struct aiocb *aiocbp) { LOADSYM(aio_return); int fd = aiocbp->aio_fildes; if (!g_libzzuf_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) return ORIG(aio_return)(aiocbp); ssize_t ret = ORIG(aio_return)(aiocbp); _zz_unlock(fd); /* FIXME: make sure we’re actually *reading* */ if (ret > 0) { _zz_setpos(fd, aiocbp->aio_offset); _zz_fuzz(fd, aiocbp->aio_buf, ret); _zz_addpos(fd, ret); } debug("%s({%i, %i, %i, %p, %li, ..., %li}) = %li", __func__, fd, aiocbp->aio_lio_opcode, aiocbp->aio_reqprio, aiocbp->aio_buf, (long int)aiocbp->aio_nbytes, (long int)aiocbp->aio_offset, (long int)ret); return ret; }
/* Sanity check, can be OK though (for instance with a character device) */ static void offset_check(int fd) { int orig_errno = errno; #if defined HAVE_LSEEK64 LOADSYM(lseek64); off64_t ret = ORIG(lseek64)(fd, 0, SEEK_CUR); #else LOADSYM(lseek); off_t ret = ORIG(lseek)(fd, 0, SEEK_CUR); #endif if (ret != -1 && ret != _zz_getpos(fd)) debug("warning: lseek(%d, 0, SEEK_CUR) = %lli (expected %lli)", fd, (long long int)ret, (long long int)_zz_getpos(fd)); errno = orig_errno; }
/* Utility function to know how many bytes are left until the end of * the file. */ size_t _zz_bytes_until_eof(int fd, size_t offset) { int orig_errno = errno; #if defined HAVE_LSEEK64 LOADSYM(lseek64); off64_t current = ORIG(lseek64)(fd, 0, SEEK_CUR); off64_t begin = ORIG(lseek64)(fd, offset, SEEK_CUR); off64_t end = ORIG(lseek64)(fd, 0, SEEK_END); ORIG(lseek64)(fd, current, SEEK_SET); #else LOADSYM(lseek); off_t current = ORIG(lseek)(fd, 0, SEEK_CUR); off_t begin = ORIG(lseek)(fd, offset, SEEK_CUR); off_t end = ORIG(lseek)(fd, 0, SEEK_END); ORIG(lseek)(fd, current, SEEK_SET); #endif errno = orig_errno; return (begin >= end) ? 0 : (size_t)(end - begin); }
RECV_T NEW(recvmsg)(int s, struct msghdr *hdr, int flags) { LOADSYM(recvmsg); ssize_t ret = ORIG(recvmsg)(s, hdr, flags); if (!must_fuzz_fd(s) || !_zz_hostwatched(s)) return ret; fuzz_iovec(s, hdr->msg_iov, ret); debug("%s(%i, %p, %x) = %li", __func__, s, hdr, flags, (long int)ret); return ret; }
ssize_t NEW(readv)(int fd, const struct iovec *iov, int count) { LOADSYM(readv); ssize_t ret = ORIG(readv)(fd, iov, count); if (!must_fuzz_fd(fd)) return ret; fuzz_iovec(fd, iov, ret); debug("%s(%i, %p, %i) = %li", __func__, fd, iov, count, (long int)ret); offset_check(fd); return ret; }
SIG_T NEW(signal)(int signum, SIG_T handler) { SIG_T ret; LOADSYM(signal); if(!_zz_signal) return ORIG(signal)(signum, handler); ret = ORIG(signal)(signum, isfatal(signum) ? SIG_DFL : handler); debug("%s(%i, %p) = %p", __func__, signum, handler, ret); return ret; }
int NEW(socket)(int domain, int type, int protocol) { LOADSYM(socket); int ret = ORIG(socket)(domain, type, protocol); if (!g_libzzuf_ready || _zz_islocked(-1) || !g_network_fuzzing) return ret; if (ret >= 0) { debug("%s(%i, %i, %i) = %i", __func__, domain, type, protocol, ret); _zz_register(ret); } return ret; }
int NEW(close)(int fd) { LOADSYM(close); /* Hey, it’s our debug channel! Silently pretend we closed it. */ if (fd == g_debug_fd) return 0; int ret = ORIG(close)(fd); if (!g_libzzuf_ready || !_zz_iswatched(fd) || _zz_islocked(fd)) return ret; debug("%s(%i) = %i", __func__, fd, ret); _zz_unregister(fd); return ret; }
int NEW(aio_read)(struct aiocb *aiocbp) { LOADSYM(aio_read); int fd = aiocbp->aio_fildes; if (!g_libzzuf_ready || !_zz_iswatched(fd) || !_zz_isactive(fd)) return ORIG(aio_read)(aiocbp); _zz_lockfd(fd); int ret = ORIG(aio_read)(aiocbp); debug("%s({%i, %i, %i, %p, %li, ..., %li}) = %i", __func__, fd, aiocbp->aio_lio_opcode, aiocbp->aio_reqprio, aiocbp->aio_buf, (long int)aiocbp->aio_nbytes, (long int)aiocbp->aio_offset, ret); return ret; }
int NEW(dup)(int oldfd) { LOADSYM(dup); int ret = ORIG(dup)(oldfd); if (!g_libzzuf_ready || _zz_islocked(-1) || !_zz_iswatched(oldfd) || !_zz_isactive(oldfd)) return ret; if (ret >= 0) { debug("%s(%i) = %i", __func__, oldfd, ret); _zz_register(ret); } return ret; }
int NEW(accept)(int sockfd, SOCKADDR_T *addr, SOCKLEN_T *addrlen) { LOADSYM(accept); int ret = ORIG(accept)(sockfd, addr, addrlen); if (!g_libzzuf_ready || _zz_islocked(-1) || !g_network_fuzzing || !_zz_iswatched(sockfd) || !_zz_isactive(sockfd)) return ret; if (ret >= 0) { if (addrlen) debug("%s(%i, %p, &%i) = %i", __func__, sockfd, addr, (int)*addrlen, ret); else debug("%s(%i, %p, NULL) = %i", __func__, sockfd, addr, ret); _zz_register(ret); } return ret; }
int NEW(dup2)(int oldfd, int newfd) { LOADSYM(dup2); int ret = ORIG(dup2)(oldfd, newfd); if (!g_libzzuf_ready || _zz_islocked(-1) || !_zz_iswatched(oldfd) || !_zz_isactive(oldfd)) return ret; if (ret >= 0) { /* We must close newfd if it was open, but only if oldfd != newfd * and if dup2() suceeded. */ if (oldfd != newfd && _zz_iswatched(newfd) && _zz_isactive(newfd)) _zz_unregister(newfd); debug("%s(%i, %i) = %i", __func__, oldfd, newfd, ret); _zz_register(ret); } return ret; }
ssize_t NEW(pread)(int fd, void *buf, size_t count, off_t offset) { LOADSYM(pread); int ret = ORIG(pread)(fd, buf, count, offset); if (!must_fuzz_fd(fd)) return ret; if (ret > 0) { long int curoff = _zz_getpos(fd); _zz_setpos(fd, offset); _zz_fuzz(fd, buf, ret); _zz_setpos(fd, curoff); } char tmp[128]; debug_str(tmp, buf, ret, 8); debug("%s(%i, %p, %li, %li) = %i %s", __func__, fd, buf, (long int)count, (long int)offset, ret, tmp); return ret; }
int NEW(sigaction)(int signum, const struct sigaction *act, struct sigaction *oldact) { int ret; LOADSYM(sigaction); if(!_zz_signal) return ORIG(sigaction)(signum, act, oldact); if(act && isfatal(signum)) { struct sigaction newact; memcpy(&newact, act, sizeof(struct sigaction)); newact.sa_handler = SIG_DFL; ret = ORIG(sigaction)(signum, &newact, oldact); } else ret = ORIG(sigaction)(signum, act, oldact); debug("%s(%i, %p, %p) = %i", __func__, signum, act, oldact, ret); return ret; }