#define _GNU_SOURCE #include #include #include #include #include #include #include #include static double probabilities[] = { [ENOSPC] = 0.01, [EIO] = 0.01, }; static bool chance(double probability) { double event = drand48(); return event < probability; } static bool inject_fault(int error) { double probability = probabilities[error]; if (chance(probability)) { errno = error; return true; } errno = 0; return false; } static ssize_t (*libc_pwrite) (int, const void *, size_t, off_t); ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) { if (libc_pwrite == NULL) { libc_pwrite = dlsym(RTLD_NEXT, "pwrite"); } if (inject_fault(ENOSPC)) { printf("%s: injecting fault NOSPC\n", __func__); return -1; } if (inject_fault(EIO)) { printf("%s: injecting fault EIO\n", __func__); return -1; } return libc_pwrite(fd, buf, count, offset); } static ssize_t (*libc_pwritev) (int, const struct iovec *, int, off_t); ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) { if (libc_pwritev == NULL) { libc_pwritev = dlsym(RTLD_NEXT, "pwritev"); } if (inject_fault(ENOSPC)) { printf("%s: injecting fault NOSPC\n", __func__); return -1; } if (inject_fault(EIO)) { printf("%s: injecting fault EIO\n", __func__); return -1; } return libc_pwritev(fd, iov, iovcnt, offset); } static int (*libc_fsync) (int); int fsync(int fd) { if (libc_fsync == NULL) { libc_fsync = dlsym(RTLD_NEXT, "fsync"); } if (inject_fault(ENOSPC)) { printf("%s: injecting fault NOSPC\n", __func__); return -1; } if (inject_fault(EIO)) { printf("%s: injecting fault EIO\n", __func__); return -1; } return libc_fsync(fd); } __attribute__((constructor)) static void init(void) { char *env_seed = getenv("UNRELIABLE_LIBC_SEED"); long seedval; if (!env_seed) { seedval = time(NULL); } else { seedval = atoi(env_seed); } printf("UNRELIABLE_LIBC_SEED = %ld\n", seedval); srand48(seedval); }