DF-4721 / trigger.c
/* * DF-4721 trigger: the DESIGNED degraded RAID-5 write (ONE down data * subdisk, no reborn trickery, no revive) on an md-backed (malloc) vinum * drive. bre5() builds the request group as * rqe[0] = parity read (launched) * rqe[1] = good data block (launched) * rqe[2] = down data block, XFR_BAD_SUBDISK (skipped at launch) * The last LAUNCHED element is rqe[1]; rqe[2] is a TRAILING skipped * element. md completes biodone() inline inside dev_dstrategy(), so * rqe[1]'s completion runs complete_raid5_write() (XOR + parity write), * whose own inline completion drives rq->active to 0 and freerq()s the * whole request - while launch_requests() is still inside its launch * loop. The loop then reads rqg->rqe[2].flags and rqg->next from the * FREED group (kmalloc freelist pointer overwrites rqg->next) and * dereferences the garbage -> kernel panic. * * buggy kernel: panic in launch_requests (Fatal trap 12, fault VA 0x0/garbage) * fixed kernel: write completes (degraded semantics), readback matches. */ #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> #define VOL "/dev/vinum/vol/rv" #define OFF (128 * 512) #define LEN (64 * 512) unsigned char wbuf[LEN], rbuf[LEN]; int main(void) { int fd, rc, i; for (i = 0; i < LEN / 2; i++) wbuf[i] = 0xC3; /* block 1 */ for (i = LEN / 2; i < LEN; i++) wbuf[i] = 0x3C; /* block 2 */ fd = open(VOL, O_RDWR); if (fd < 0) { perror("open"); return 2; } if (lseek(fd, OFF, SEEK_SET) < 0) { perror("lseek"); return 2; } rc = write(fd, wbuf, LEN); if (rc != LEN) { perror("write"); printf("DF-4721 RESULT: write FAILED (%d)\n", rc); return 0; } printf("DF-4721: write OK (degraded write survived)\n"); sleep(1); if (lseek(fd, OFF, SEEK_SET) < 0) { perror("lseek2"); return 2; } rc = read(fd, rbuf, LEN); if (rc != LEN) { perror("read"); printf("DF-4721 RESULT: read FAILED\n"); return 0; } for (i = 0; i < LEN; i++) if (rbuf[i] != wbuf[i]) { printf("DF-4721 RESULT: readback mismatch at %d (%02x != %02x)\n", i, rbuf[i], wbuf[i]); return 1; } printf("DF-4721 RESULT: readback matches, no panic\n"); return 0; } |