You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux内核模块struct nameidata/open_flags无法识别问题求助

内核模块kprobe挂载path_openat时struct nameidata/open_flags未定义问题

问题背景

开发Linux内核模块,为path_openat函数挂载kprobe以实现文件/目录的open、unlink、rename等操作监控。处理函数首个参数struct nameidata时,虽已引入<linux/namei.h>,仍触发编译错误:invalid use of undefined type struct nameidata,struct open_flags也存在同样问题。手动自定义结构体定义会损害模块的可移植性,需找到合规解决办法。

前置处理代码

static int openat_pre_handler(struct kretprobe_instance *p, struct pt_regs *the_regs){
    // path openat pre handler

    struct nameidata * nd;
    struct open_flags * op_flags;
    struct inode * inode;
    struct filename * pathname_struct;
    const char *pathname;
    int flags;

    // 模块处于关闭或记录关闭状态时,不执行后置处理
    if(monitor->state == 0 || monitor->state == 1)
        goto end;


    atomic_inc((atomic_t*)&open_audit_counter);

    // x86-64 系统调用传参约定:%rdi, %rsi, %rdx, %r10, %r8 和 %r9
   
    /*path_openat(struct nameidata *nd, const struct open_flags *op, unsigned flags)*/

    // nameidata是第一个参数,包含inode和文件名信息
    nd = (struct nameidata *) the_regs->di; 
    inode = nd->inode;
    pathname_struct = nd->name;
    pathname = pathname_struct->name;

    // open_flag是第二个参数
    op_flags = (struct open_flags *) the_regs->si; 
    flags = op_flags->open_flag;
    
    // 检查文件是否以只写或读写模式打开
    if (flags & O_WRONLY || flags & O_RDWR){
        
        // 检查文件是否受保护
        if (inode_in_protected_paths(inode->i_ino)){
            // 写入日志记录访问拦截
            printk("%s: Access on %s blocked correctly \n", MODNAME,pathname);
            //print_flag(flags);
            // 需要执行kretprobe后置处理:拦截该访问
            return 0;
        }

    } 

end: 
    // 不执行后置处理,访问合法
    return 1;
}

头文件引入列表

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/fs.h>
#include <linux/printk.h>    
#include <linux/spinlock.h>  
#include <linux/file.h>
#include <linux/version.h>
#include <linux/path.h> 
#include <linux/slab.h>
#include <linux/fdtable.h>
#include <linux/fs_struct.h>
#include <linux/namei.h>
#include <linux/dcache.h>

解决办法

1. 补充缺失的头文件

struct open_flags的定义位于<linux/open.h>中,当前头文件列表未引入该文件,添加:

#include <linux/open.h>

2. 适配内核版本的结构体可见性

struct nameidata在5.x及以上的新内核中,定义被标记为内部可见,直接引用会触发未定义错误。可通过两种方式处理:

  • 启用编译宏:添加内核编译宏-DCONFIG_FS_POSIX_ACL或对应版本的特定宏,使结构体定义对模块可见;
  • 偏移量访问:通过内核调试工具pahole分析目标内核版本中struct nameidata成员的内存偏移量,再通过指针计算间接访问成员。示例:
// 假设通过pahole获取到nd->inode的偏移量为0x10
#define NAMEIDATA_INODE_OFFSET 0x10
struct inode *inode = *(struct inode **)((char *)nd + NAMEIDATA_INODE_OFFSET);

3. 替换为稳定探测点

path_openat属于内核内部函数,接口稳定性差。可转而探测用户态sys_openat系统调用,或内核中更稳定的do_sys_openat函数,这类函数的参数定义在公共头文件中更易访问。

4. 开启内核调试配置

确保内核编译时开启CONFIG_DEBUG_INFO、CONFIG_PROC_FS选项,这些配置会让内核结构体的完整定义对模块可见。


内容的提问来源于stack exchange,提问作者Luca Esposito

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 09:32:44