[已解决]内核里与读写文件有关的问题

内核编译和嵌入式产品的设计与开发
回复
头像
wxf
帖子: 50
注册时间: 2008-05-28 8:50

[已解决]内核里与读写文件有关的问题

#1

帖子 wxf » 2024-01-20 19:56

我通过hook系统调用,实现应用层度“读加密文件时的自动解密”和“写文件时的自动加密”

hook了 openat、read、write、fstat等函数

测试读,暂时没问题,能解密

测试写,有问题!
printk输出如下:
无标题.jpg
上图是我应用层点保存时触发的输出。看样子,点保存后,程序调用openat函数重新打开文件,fd是10; 然后lseek了一次,不过这个事件在本次测试里没什么意义; 程序然后close了这个fd。这里就有问题了,为啥要close呢? 我为了避免影响无关文件,所以openat时记录了加密文件的fd,close时会把这个fd从链表里清理掉。它close,我就得清理掉,然后下边write时就不对了, wirte调用的hook版本认为参数里的fd代表非加密文件,所以没有给文件加文件头,也没有走加密数据分支,保存的文件于是就变成明文了。

我不明白,应用层wirte文件之前,为啥要把fd close掉?close之后的write函数使用的fd是怎么来的?
上次由 wxf 在 2024-02-20 12:51,总共编辑 2 次。
头像
astolia
论坛版主
帖子: 6454
注册时间: 2008-09-18 13:11

Re: 【求助】内核里与读写文件有关的问题

#2

帖子 astolia » 2024-01-21 12:01

wxf 写了: 2024-01-20 19:56 程序然后close了这个fd。这里就有问题了,为啥要close呢?
去问程序的作者啊?
wxf 写了: 2024-01-20 19:56 close之后的write函数使用的fd是怎么来的?
能创建fd的系统调用又不是只有openat,就像能读写的不只read/write,关闭fd的不只close
你这个图最多只能表示目标程序调用过这些系统调用,不代表它没用过其他的
头像
wxf
帖子: 50
注册时间: 2008-05-28 8:50

Re: 【求助】内核里与读写文件有关的问题

#3

帖子 wxf » 2024-01-21 19:06

astolia 写了: 2024-01-21 12:01 能创建fd的系统调用又不是只有openat,就像能读写的不只read/write,关闭fd的不只close
你这个图最多只能表示目标程序调用过这些系统调用,不代表它没用过其他的
我又加了些输出语句,发现openat函数里边判断文件是不是加密时出错了。dss_is_crypt_file这个函数不符合预期

代码: 全选


static bool dss_is_crypt_file(const char*  filename)
{
    struct file* file =  filp_open(filename, O_RDONLY, 0);
    if (IS_ERR(file))
    {
        printk("%s, %d, filp_open failed, filename:[%s]\n", __FUNCTION__, __LINE__, filename);
        return false;
    }

    mm_segment_t old_fs = get_fs();
    set_fs(KERNEL_DS);

    loff_t pos = 0;
    char buf[9] = { 0 };
    loff_t ret = vfs_read(file, buf, 8, &pos);
    //file->f_pos = pos;

    set_fs(old_fs);

    filp_close(file,0);

    printk("%s, %d, filename:[%s], first eight chars :%s, read count:%lld, pos:%lld\n", __FUNCTION__, __LINE__, filename, buf, ret, pos);

    if (strcmp(buf, DSS_STD_FLAG) == 0)
        return true;
    else
        return false;
}


long dss_openat(struct pt_regs* regs)
{
    //int dfd = regs->di;
    char __user* user_filename = regs->si;
    int flags = regs->dx;

    char filename[DSS_FILE_PATH] = { 0 };
    strncpy_from_user(filename, user_filename, strnlen_user(user_filename, DSS_FILE_PATH - 1));

    //如果当前进程不是加密进程
    if (!IsSensitive(current->pid))
    {
        //printk("%s, %d is not sensitive,filename:%s\n", __FUNCTION__, current->pid, filename);
        return orig_openat(regs);
    }

    .......

    //文件不存在
    if (!file_exists)
    {
       .......
    }
    //文件存在
    else
    {
        if (dss_is_crypt_file(filename))
        {
            printk("%s, %d, file [%s] is crypted, fd is [%d]\n", __FUNCTION__, __LINE__, filename,fd);
            savefd(current->pid, fd);
        }     
        else
            printk("%s, %d, file [%s] is not crypted, fd is [%d]\n", __FUNCTION__, __LINE__, filename, fd);
    }

    return fd;
}

输出是这样的:
截图1705835059.jpg
为什么一开始vfs_read能读到文件的前八个字节,后边就不读到了,读到的长度是0
头像
wxf
帖子: 50
注册时间: 2008-05-28 8:50

Re: 【求助】内核里与读写文件有关的问题

#4

帖子 wxf » 2024-01-21 20:37

还要问一个问题:一个进程退出了,module如何得到通知?
有没有一种机制,比如注册一个响应函数,进程退出时,进程管理器调用这个函数
头像
astolia
论坛版主
帖子: 6454
注册时间: 2008-09-18 13:11

Re: 【求助】内核里与读写文件有关的问题

#5

帖子 astolia » 2024-01-21 22:38

wxf 写了: 2024-01-21 19:06 为什么一开始vfs_read能读到文件的前八个字节,后边就不读到了,读到的长度是0
本来在2楼的帖子里我写了些话,但是觉得说得太重了就删了。看你还这个样子那不妨说明白一点:你先把目标程序的执行流程弄清楚,不要再传些没头没脑的图和代码了,我没兴趣也没这个闲工夫来搞破译。

一个很常见的操作是,读入全部内容到内存,修改就在内存里改,保存时打开文件用O_TRUNC,再把内存里的全部写入文件。这种情况下在打开操作执行后再去读,自然读到的是一个空文件

还有,别再给我发站内信了。
头像
astolia
论坛版主
帖子: 6454
注册时间: 2008-09-18 13:11

Re: 【求助】内核里与读写文件有关的问题

#6

帖子 astolia » 2024-01-21 22:56

wxf 写了: 2024-01-21 20:37 还要问一个问题:一个进程退出了,module如何得到通知?
有没有一种机制,比如注册一个响应函数,进程退出时,进程管理器调用这个函数
应该可以用kprobes机制来监听特定函数比如do_exit的调用,或者看看ftrace机制是怎么处理sched_switch/sched_process_exit事件的,只要内核编译时没把这些机制裁剪掉
头像
wxf
帖子: 50
注册时间: 2008-05-28 8:50

Re: 【求助】内核里与读写文件有关的问题

#7

帖子 wxf » 2024-01-21 23:41

astolia 写了: 2024-01-21 22:38
不好意思,是我唐突了。感谢回复,我再研究一下
上次由 wxf 在 2024-01-22 0:01,总共编辑 1 次。
头像
wxf
帖子: 50
注册时间: 2008-05-28 8:50

Re: 【求助】内核里与读写文件有关的问题

#8

帖子 wxf » 2024-01-21 23:51

刚检查了一下,openat时真的有TRUNC标记。那我再修改一下代码看看
回复