当前位置: 首页 > news >正文

Linux integrity iint节点与ima_file_mmap测量

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组织:

```c
struct 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节点的查询树:

```c
static 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;
else
return iint;
}

return NULL;
}
```

ima_file_mmap是IMA在mmap系统调用中执行完整性测量的钩子,注册在security/integrity/ima/ima_main.c中:

```c
int 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测量操作的核心函数,处理所有测量、评估和审计操作:

```c
static 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节点:

```c
int 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测量列表,供远程证明使用:

```c
void 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节点:

```c
struct 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;
else
p = &(*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 func=MMAP_CHECK mask=MAY_EXEC"规则指示对所有mmap可执行映射的文件执行测量。每次文件映射时ima_file_mmap触发process_measurement,对照策略规则决定是否需要执行hash测量并扩展TPM PCR,确保运行时可执行文件的完整性可追溯。

http://www.gsyq.cn/news/1515668.html

相关文章:

  • 2026杭州美院附中考前班评测:四家机构核心维度对比 - 优质品牌商家
  • 别再手动调API了!用GPT-3.5-turbo-16k的函数调用,5分钟搞定天气查询机器人
  • MYSQL RR 解决“脏读+不可重复读“和“幻读“的本质区别
  • 如何免费实现7种音频格式高效转换:FlicFlac专业解决方案指南
  • 2026年 江西凉亭厂家推荐榜单:六角/八角/双层/四角凉亭,古韵匠心与户外园林精品之选 - 品牌发掘
  • C盘存储爆红,哪些文件类型可以安全删除?一张清单分三档
  • 兰州黄金回收实测 余生珍宝六店行情解析 - 余生黄金回收
  • 2026年英文降AIGC率指南:别盲目同义词替换!5种降AI高效方法实测(附工具测评) - 降AI实验室
  • 别再只会录宏了!WPS JS宏实战:用filter和箭头函数5分钟搞定数据清洗
  • C盘大文件怎么搬到D盘或其他分区?从定位到迁移的完整操作
  • 2026甘孜州权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • 2026年q2正规青年旅行社官网品牌技术维度解析:美国旅游/318川藏线自驾游/中国青年旅行社官网/优选推荐 - 优质品牌商家
  • 保姆级教程:用ADB命令备份与删除长安UNI-V车机自带软件(附完整命令清单)
  • Windows电脑频繁弹广告怎么彻底清除?从定位来源到卸载残留的完整方法
  • 长沙鑫合诚新能源物流车联系电话多少?快速获取 - 工业品牌热点
  • 别再手动填数据了!Vivado 2023.2 中一键生成 .coe 文件并配置 ROM IP 核的保姆级教程
  • 2026实力之选:广东单头加热管厂家如何应对全场景定制挑战? - 品牌发掘
  • 临汾余生黄金回收实测 2026六家门店价格对比 - 余生黄金回收
  • 靠谱的HIP热等静压推荐供应商,顶立科技,售后响应快 - 工业品牌热点
  • Python原生OLAP BI平台:atoti实战指南
  • 荆州闲置黄金变现六家正规机构盘点 - 余生黄金回收
  • AR 巡检落地案例与优质厂商推荐
  • 球对称流形上的Sobolev嵌入定理与应用
  • 多维聚合中的数据变形术:从GROUP BY到决策表的四步重构
  • 性价比高的托育机构,湘蒙在宝宝语言启蒙培养方面表现突出 - 工业品牌热点
  • 建筑保温材料厂主要分布在哪些产区?全国版图盘点
  • Xilinx FPGA上LVDS与CameraLink高速图像接口的完整工程实现(含VHDL/Verilog源码及Vivado工程)
  • 2026阜阳市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
  • 构建高性能AI内容创作引擎:ComfyUI模块化架构深度解析
  • 荆州黄金回收实测六家靠谱门店 - 余生黄金回收