Linux integrity iint节点与ima_file_mmap测量integrity子系统的核心数据结构是struct integrity_iint它为每个被监控的inode维护完整性元数据。IMA(Integrity Measurement Architecture)在file_mmap钩子中执行文件mmap映射时的完整性测量确保映射到进程地址空间的可执行文件内容在测量基准上未被篡改。struct integrity_iint定义在security/integrity/iint.c中通过inode的iint_cache和rb_tree组织cstruct integrity_iint {struct rb_node rb_node; /* 红黑树节点以inode指针排序 */struct rcu_head rcu; /* RCU回调 */struct inode *inode; /* 关联的inode指针 */u64 version; /* inode版本号检测文件变更 */unsigned char flags; /* IMA状态标志位 */enum integrity_status ima_file_status : 4; /* 文件完整性状态 */enum integrity_status ima_mmap_status : 4; /* mmap完整性状态 */enum integrity_status ima_bprm_status : 4; /* exec完整性状态 */enum integrity_status ima_read_status : 4; /* 读取完整性状态 */enum integrity_status ima_creds_status : 4; /* 凭证完整性状态 */struct ima_digest_data *ima_hash; /* 文件内容的完整性hash */};integrity_iint_cache是全局的管理结构保存所有iint节点的查询树cstatic struct rb_root integrity_iint_tree RB_ROOT;static DEFINE_SPINLOCK(integrity_iint_lock);static struct kmem_cache *iint_cache;struct integrity_iint *integrity_iint_find(struct inode *inode){struct rb_node *n integrity_iint_tree.rb_node;/* 以inode指针为key在红黑树中查找 */while (n) {struct integrity_iint *iint rb_entry(n, struct integrity_iint, rb_node);if (inode iint-inode)n n-rb_left;else if (inode iint-inode)n n-rb_right;elsereturn iint;}return NULL;}ima_file_mmap是IMA在mmap系统调用中执行完整性测量的钩子注册在security/integrity/ima/ima_main.c中cint ima_file_mmap(struct file *file, unsigned long prot, unsigned long flags){u32 secid;int ret;if (!file)return 0;/* 仅检查可执行映射PROT_EXEC且非PROT_WRITE */if (!(prot PROT_EXEC))return 0;/* 跳过写回映射(writeback mapping)中的mmap检查 */if (flags MAP_SHARED prot PROT_WRITE)return 0;/* 获取文件的LSM安全ID */security_task_getsecid(current, secid);/* 执行完整性测量策略 */return process_measurement(file, current_cred(), secid, NULL,0, MAY_EXEC, MMAP_CHECK);}process_measurement是IMA测量操作的核心函数处理所有测量、评估和审计操作cstatic int process_measurement(struct file *file, const struct cred *cred,u32 secid, char *buf, loff_t size,int mask, enum ima_hooks func){struct inode *inode file_inode(file);struct integrity_iint *iint;int rc 0;int action 0;u64 pathname 0;/* 查找或创建inode对应的iint节点 */iint integrity_iint_find(inode);if (!iint) {/* 首次访问此inode分配新的iint */iint integrity_iint_insert(inode);if (!iint)return -ENOMEM;}/* 锁定iint防止并发测量 */mutex_lock(iint-mutex);/* 检查策略是否要求测量此文件 */action ima_get_action(inode, cred, secid, mask, func, pcr, template,func_retry);/* 如果inode版本变化说明文件已被修改需要重新测量 */if (action IMA_MEASURE) {if (iint-flags IMA_MEASURED iint-version inode-i_version)action ~IMA_MEASURE;}/* 执行完整性测量 */if (action IMA_MEASURE) {rc ima_collect_measurement(iint, file, buf, size, hash_algo);if (rc 0)goto out;/* 将测量结果扩展到TPM PCR并存入IMA测量列表 */ima_store_measurement(iint, file, pathname, cred, secid,pcr, template, func);iint-flags | IMA_MEASURED;iint-version inode-i_version;}/* 执行完整性评估(如果策略要求) */if (action IMA_APPRAISE) {rc ima_appraise_measurement(func, iint, file, pathname,cred, secid, buf, size);if (rc -EACCES)goto out;}out:mutex_unlock(iint-mutex);return rc;}ima_collect_measurement计算文件内容的hash值并存入iint节点cint ima_collect_measurement(struct integrity_iint *iint, struct file *file,void *buf, loff_t size, enum hash_algo algo){struct ima_digest_data *hash;int result -ENOMEM;/* 分配hash数据结构 */hash kzalloc(sizeof(*hash) sizeof(struct ima_field_data), GFP_NOFS);if (!hash)return -ENOMEM;hash-algo algo;hash-length hash_digest_size[algo];/* 使用内核加密API计算文件内容的hash */result kernel_read_file(file, 0, buf, size, NULL, READING_POLICY);if (result 0)goto out;result ima_calc_field_array_hash(hash, file);if (result 0)goto out;/* 释放旧的hash并替换为新的测量结果 */kfree(iint-ima_hash);iint-ima_hash hash;out:return result;}ima_store_measurement将测量结果添加到PCR扩展和IMA测量列表供远程证明使用cvoid ima_store_measurement(struct integrity_iint *iint, struct file *file,const unsigned char *filename,struct evm_ima_xattr_data *xattr_value,int violation, struct ima_template_desc *template_desc){static const char op[] add_template_measure;static const char audit_cause[] missing_template;struct ima_template_entry *entry;int violation 0;int result;/* 创建模板条目包含文件元数据和hash */result ima_alloc_init_template(iint, file, filename, xattr_value,template_desc, entry);if (result 0)return;/* 扩展TPM PCR */result ima_extend_pcr(entry, iint-ima_hash-algo);if (result)goto out;/* 将测量加入全局测量列表 */result ima_add_template_entry(entry, violation, op, file, audit_cause);out:if (result)ima_free_template_entry(entry);}integrity_iint_insert在红黑树中插入新的iint节点cstruct integrity_iint *integrity_iint_insert(struct inode *inode){struct integrity_iint *iint;struct rb_node **p, *parent NULL;iint kmem_cache_alloc(iint_cache, GFP_NOFS);if (!iint)return NULL;memset(iint, 0, sizeof(*iint));iint-inode inode;mutex_init(iint-mutex);spin_lock(integrity_iint_lock);p integrity_iint_tree.rb_node;while (*p) {struct integrity_iint *test rb_entry(*p, struct integrity_iint, rb_node);parent *p;if (inode test-inode)p (*p)-rb_left;elsep (*p)-rb_right;}rb_link_node(iint-rb_node, parent, p);rb_insert_color(iint-rb_node, integrity_iint_tree);spin_unlock(integrity_iint_lock);return iint;}IMA的测量策略通过内核启动参数ima_policy或/sys/kernel/security/ima/policy接口动态加载。策略规则定义哪些文件需要被测量例如measure funcMMAP_CHECK maskMAY_EXEC规则指示对所有mmap可执行映射的文件执行测量。每次文件映射时ima_file_mmap触发process_measurement对照策略规则决定是否需要执行hash测量并扩展TPM PCR确保运行时可执行文件的完整性可追溯。