DF-0755 / race_harness_fixed.c
/* * DF-0755 - "fixed" variant of the userspace harness. * * Identical to race_harness.c except the index increment + wrap are * serialized by a pthread spinlock, mirroring the kernel fix.diff which * wraps tcp_debx in `struct spinlock tcp_debx_spin` and takes it around * `slot = tcp_debx++; if (tcp_debx == TCP_NDEBUG) tcp_debx = 0;`. * * With the lock, the index is mathematically unable to exceed TCP_NDEBUG-1. * Contrast with race_harness.c (no lock) which routinely blows past the * bound by millions of slots per run. * * Build: cc -O2 -pthread -o race_harness_fixed race_harness_fixed.c * Run: ./race_harness_fixed */ #include <stdio.h> #include <stdlib.h> #include <pthread.h> #define TCP_NDEBUG 100 #define NTHREADS 8 #define ITERS 2000000 static struct { char pad[64]; } tcp_debug[TCP_NDEBUG]; static volatile int tcp_debx = 0; /* pthread spinlock stands in for the kernel's `struct spinlock`. */ static pthread_spinlock_t tcp_debx_spin; static volatile int max_idx_seen = 0; static volatile int oob_count = 0; static void * tracer(void *arg) { (void)arg; for (long i = 0; i < ITERS; i++) { int slot; struct { char pad[64]; } *td; pthread_spin_lock(&tcp_debx_spin); slot = tcp_debx++; if (tcp_debx == TCP_NDEBUG) tcp_debx = 0; pthread_spin_unlock(&tcp_debx_spin); td = &tcp_debug[slot]; (void)td; if (slot > max_idx_seen) max_idx_seen = slot; if (slot >= TCP_NDEBUG) oob_count++; } return NULL; } int main(void) { pthread_t th[NTHREADS]; pthread_spin_init(&tcp_debx_spin, 0); for (int i = 0; i < NTHREADS; i++) pthread_create(&th[i], NULL, tracer, NULL); for (int i = 0; i < NTHREADS; i++) pthread_join(th[i], NULL); printf("TCP_NDEBUG (array bound) = %d\n", TCP_NDEBUG); printf("max slot index used = %d\n", max_idx_seen); printf("OOB writes (slot>=100) = %d\n", oob_count); if (max_idx_seen < TCP_NDEBUG) { printf("RESULT: INDEX BOUNDED -- spinlock keeps tcp_debx in [0,99]\n"); printf("=> fix closes the race; no OOB write possible\n"); return 0; } else { printf("RESULT: UNEXPECTED OOB (lock failed?)\n"); return 1; } } |