testing: Add unreliable libc

This commit is contained in:
Pekka Enberg
2025-08-18 15:49:59 +03:00
parent 9233f48e08
commit 19456147ec
2 changed files with 116 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
CC = gcc
CFLAGS = -Wall -Wextra -fPIC
LDFLAGS = -shared
TARGET = unreliable-libc.so
SRCS = file.c
OBJS = $(SRCS:.c=.o)
.PHONY: all clean
all: $(TARGET)
$(TARGET): $(OBJS)
$(CC) $(LDFLAGS) -o $@ $^ -ldl
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET)
install: $(TARGET)
install -m 755 $(TARGET) /usr/local/lib
uninstall:
rm -f /usr/local/lib/$(TARGET)

View File

@@ -0,0 +1,91 @@
#define _GNU_SOURCE
#include <sys/uio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <dlfcn.h>
#include <errno.h>
#include <stdio.h>
#include <time.h>
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)
{
srand48(time(NULL));
}