// https://syzkaller.appspot.com/bug?id=97947e18678d4687bc0da7d8be28ed6fb6bbd7f3 #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include void write_file(const char *path, const char *val) { int fd = open(path, O_WRONLY); if (fd < 0) { printf("[-] Failed to open %s: %s\n", path, strerror(errno)); exit(1); } int res = write(fd, val, strlen(val)); if (res < 0) { printf("[-] Failed to write to %s: %s\n", path, strerror(errno)); exit(1); } res = close(fd); if (res < 0) { printf("[-] Failed to close %s: %s\n", path, strerror(errno)); exit(1); } } void *thread_a(void *arg) { const char *enable_path = "/sys/kernel/config/nvmet/subsystems/test/namespaces/1/enable"; while (1) { int fd = open(enable_path, O_WRONLY); if (fd >= 0) { if (write(fd, "1", 1) < 0) {} close(fd); } fd = open(enable_path, O_WRONLY); if (fd >= 0) { if (write(fd, "0", 1) < 0) {} close(fd); } } return NULL; } void *thread_b(void *arg) { const char *configfs_file = "/sys/kernel/config/nvmet/subsystems/test/namespaces/1/device_path"; char buf[1]; while (1) { int fd = open(configfs_file, O_RDONLY); if (fd >= 0) { if (read(fd, buf, 1) < 0) {} close(fd); } } return NULL; } int main(void) { setvbuf(stdout, NULL, _IONBF, 0); // Mount securityfs int res = mkdir("/sys/kernel/security", 0755); if (res < 0 && errno != EEXIST) { printf("[-] Failed to mkdir /sys/kernel/security: %s\n", strerror(errno)); } res = mount("securityfs", "/sys/kernel/security", "securityfs", 0, NULL); if (res < 0 && errno != EBUSY) { printf("[-] Failed to mount securityfs: %s\n", strerror(errno)); } else { printf("[+] mount securityfs successful.\n"); } // Load IMA Policy int ima_fd = open("/sys/kernel/security/ima/policy", O_WRONLY); if (ima_fd >= 0) { const char *policy = "measure func=FILE_CHECK\n"; if (write(ima_fd, policy, strlen(policy)) < 0) { printf("[-] Failed to write IMA policy: %s\n", strerror(errno)); } else { printf("[+] IMA policy loaded.\n"); } close(ima_fd); } else { printf("[-] Failed to open IMA policy: %s\n", strerror(errno)); } res = mkdir("/sys/kernel/config", 0755); if (res < 0 && errno != EEXIST) { printf("[-] Failed to mkdir /sys/kernel/config: %s\n", strerror(errno)); } res = mount("configfs", "/sys/kernel/config", "configfs", 0, NULL); if (res < 0 && errno != EBUSY) { printf("[-] Failed to mount configfs: %s\n", strerror(errno)); exit(1); } printf("[+] mount configfs successful.\n"); res = mkdir("/sys/kernel/config/nvmet", 0755); if (res < 0 && errno != EEXIST) { printf("[-] Failed to mkdir /sys/kernel/config/nvmet: %s\n", strerror(errno)); } res = mkdir("/sys/kernel/config/nvmet/subsystems", 0755); if (res < 0 && errno != EEXIST) { printf("[-] Failed to mkdir subsystems: %s\n", strerror(errno)); exit(1); } res = mkdir("/sys/kernel/config/nvmet/subsystems/test", 0755); if (res < 0 && errno != EEXIST) { printf("[-] Failed to mkdir subsystem test: %s\n", strerror(errno)); exit(1); } res = mkdir("/sys/kernel/config/nvmet/subsystems/test/namespaces", 0755); if (res < 0 && errno != EEXIST) { printf("[-] Failed to mkdir namespaces: %s\n", strerror(errno)); exit(1); } res = mkdir("/sys/kernel/config/nvmet/subsystems/test/namespaces/1", 0755); if (res < 0 && errno != EEXIST) { printf("[-] Failed to mkdir namespace 1: %s\n", strerror(errno)); exit(1); } const char *backing_file = "./test_backing_file"; int fd = open(backing_file, O_CREAT | O_RDWR, 0644); if (fd < 0) { printf("[-] Failed to open backing file: %s\n", strerror(errno)); exit(1); } char data[4096]; memset(data, 'A', sizeof(data)); res = write(fd, data, sizeof(data)); if (res < 0) { printf("[-] Failed to write to backing file: %s\n", strerror(errno)); exit(1); } res = ftruncate(fd, 1024 * 1024); if (res < 0) { printf("[-] Failed to ftruncate backing file: %s\n", strerror(errno)); exit(1); } res = close(fd); if (res < 0) { printf("[-] Failed to close backing file: %s\n", strerror(errno)); exit(1); } // Force IMA measurement fd = open(backing_file, O_RDONLY); if (fd < 0) { printf("[-] Failed to open backing file for read: %s\n", strerror(errno)); exit(1); } char buf[1]; if (read(fd, buf, 1) < 0) { printf("[-] Failed to read backing file: %s\n", strerror(errno)); exit(1); } close(fd); printf("[+] read backing file successful.\n"); const char *dev_path_attr = "/sys/kernel/config/nvmet/subsystems/test/namespaces/1/device_path"; write_file(dev_path_attr, backing_file); printf("[+] write device_path successful.\n"); pthread_t t1, t2; res = pthread_create(&t1, NULL, thread_a, NULL); if (res != 0) { printf("[-] Failed to create thread_a: %s\n", strerror(res)); exit(1); } printf("[+] create thread_a successful.\n"); res = pthread_create(&t2, NULL, thread_b, NULL); if (res != 0) { printf("[-] Failed to create thread_b: %s\n", strerror(res)); exit(1); } printf("[+] create thread_b successful.\n"); sleep(5); printf("[+] sleep successful.\n"); return 0; }