最近看的一个问题,消息队列可以创建,但是不能获取属性,也不能发消息,返回错误为:EBADF Bad file descriptor

经过打点,确认走入了这个流程:

SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes,
const struct mq_attr __user *, u_mqstat,
struct mq_attr __user *, u_omqstat)
{
int ret;
struct mq_attr mqstat, omqstat;
struct fd f;
struct inode *inode;
struct mqueue_inode_info *info; if (u_mqstat != NULL) {
if (copy_from_user(&mqstat, u_mqstat, sizeof(struct mq_attr)))
return -EFAULT;
if (mqstat.mq_flags & (~O_NONBLOCK))
return -EINVAL;
} f = fdget(mqdes);
if (!f.file) {
ret = -EBADF;
goto out;
} inode = file_inode(f.file);
if (unlikely(f.file->f_op != &mqueue_file_operations)) {--------走的这个分支,导致错误
ret = -EBADF;
goto out_fput;
}

这个分支判断按道理也没什么问题,因为既然是消息队列,那么file->f_op就应该是 mqueue_file_operations 。

static int do_dentry_open(struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
{
。。。。。 f->f_op = fops_get(inode->i_fop);
}

根据alloc_inode的流程:

static struct inode *alloc_inode(struct super_block *sb)
{
。。。。 if (unlikely(inode_init_always(sb, inode))) {
。。。。
} int inode_init_always(struct super_block *sb, struct inode *inode)
{
...
inode->i_op = &empty_iops;----------初始化默认值
inode->i_fop = &no_open_fops;-------初始化的默认值
...
}

正常情况下在mq_open-->mqueue_create-->mqueue_get_inode 中会将

inode->i_fop = &mqueue_file_operations;

这样在 do_dentry_open 的时候,会将对应的 f->f_op = fops_get(inode->i_fop);

也就是正常的file.f_op为:

struct file.f_op ffff883f53079500
f_op = 0xffffffff81690fa0 <mqueue_file_operations>

mqueue_file_operations = $1 = {
owner = 0x0,
llseek = 0xffffffff811e00d0 <default_llseek>,
read = 0xffffffff81278220 <mqueue_read_file>,
write = 0x0,
aio_read = 0x0,
aio_write = 0x0,
readdir = 0x0,
poll = 0xffffffff812781a0 <mqueue_poll_file>,
unlocked_ioctl = 0x0,
compat_ioctl = 0x0,
mmap = 0x0,
open = 0x0,
flush = 0xffffffff812790f0 <mqueue_flush_file>,
release = 0x0,
fsync = 0x0,
aio_fsync = 0x0,
fasync = 0x0,
lock = 0x0,
sendpage = 0x0,
get_unmapped_area = 0x0,
check_flags = 0x0,
flock = 0x0,
splice_write = 0x0,
splice_read = 0x0,
{
setlease = 0x0,
__UNIQUE_ID_rh_kabi_hide5 = {
setlease = 0x0
},
{<No data fields>}
},
fallocate = 0x0,
show_fdinfo = 0x0
}

而异常情况下的file.f_op为:

struct file.f_op 0xffff883e8d075b00
f_op = 0xffff883ba95251b8

struct file_operations {
owner = 0x0,
llseek = 0xffffffff811e00d0 <default_llseek>,
read = 0xffffffff81278220 <mqueue_read_file>,
write = 0xffffffffa04e97f0 <rfs_write>,--------------redirfs模块修改的
aio_read = 0x0,
aio_write = 0x0,
readdir = 0x0,
poll = 0xffffffff812781a0 <mqueue_poll_file>,
unlocked_ioctl = 0x0,
compat_ioctl = 0x0,
mmap = 0xffffffffa04e9380 <rfs_mmap>,---------------redirfs模块修改的
open = 0xffffffffa04ea3a0 <rfs_open>,---------------redirfs模块修改的
flush = 0xffffffff812790f0 <mqueue_flush_file>,
release = 0xffffffffa04e9d50 <rfs_release>,---------redirfs模块修改的
fsync = 0x0,
aio_fsync = 0x0,
fasync = 0x0,
lock = 0x0,
sendpage = 0x0,
get_unmapped_area = 0x0,
check_flags = 0x0,
flock = 0x0,
splice_write = 0x0,
splice_read = 0x0,
{
setlease = 0x0,
__UNIQUE_ID_rh_kabi_hide5 = {
setlease = 0x0
},
{<No data fields>}
},
fallocate = 0x0,
show_fdinfo = 0x0
}

 

而修改这个的模块为redirfs,是趋势科技的一个内核模块,看起来是用来给他们的filter服务的,普通的文件打开时,只是检查file.f_op不为NULL,但是msgqueue则多了一项检查,导致检查不通过。

lsmod |grep -i redirfs
redirfs 79430 1 gsch lsmod |grep -i gsch
gsch 93171 8
redirfs 79430 1 gsch locate redirfs
/opt/ds_agent/3.10.0-229.11.1.el7.x86_64/redirfs.ko

虽然这个问题,趋势可以使用最暴力的直接修改sys_call_table 的方式来规避这个问题:

0xffffffffa0514cf0 <gsch_write_hook_fn>
0xffffffffa0516a80 <gsch_open_hook_fn>
0xffffffffa05158a0 <gsch_close_hook_fn>
0xffffffffa0514dd0 <gsch_pwrite64_hook_fn>
0xffffffffa0514ec0 <gsch_writev_hook_fn>
0xffffffffa0515a80 <gsch_dup2_hook_fn>
0xffffffffa05149a0 <gsch_exit_hook_fn>
0xffffffffa0514fa0 <gsch_unlink_hook_fn>
0xffffffffa0514940 <gsch_getpgid_hook_fn>
0xffffffffa0514a20 <gsch_exit_group_hook_fn>

但是这样明显侵入性太强了,毕竟这年头通过修改sys_call来完成功能的内核模块太多了,这样的话存在加载顺序的bug之类的。

那假设是我们使用redirfs来完成filter这种辅助功能,应该怎么修改呢?把判断去掉么,因为判断 mqueue_file_operations 这个指针的地方还蛮多的

几乎所有的mq开头的系统调用都需要篡改,似乎也没有好的办法,回到问题的原点,趋势干嘛不对msgqueue这种文件类型过滤掉呢?

趋势科技 redirfs模块的一个小问题的更多相关文章

  1. windows平台python svn模块的一个小 bug

    环境 编程语言版本:python 2.7 操作系统:win10 64位 模块名:svn svn  checkout时报错 File "D:\Python27\lib\site-package ...

  2. 关于ASPOSE.WORD使用上的一个小问题

    最近实习期间负责了公司某个项目的一个功能模块里面的word导出功能,使用的是ASPOSE.WORD类库,但是经常导出时候会遇到图中的问题,大概意思就是两个表格不能跨在一起,调试了好几次还是没发现具体的 ...

  3. 关于sniff函数的一个小坑

    最近在用scapy模块写一个关于WiFi的脚本时用到sniff函数,其中遇到了一个小坑,记录如下: sniff函数是在指定网卡上每次嗅探到一个数据包后然后将它传给prn指定的函数.

  4. 一个小框架,基于rx_retrofit2_mvp

    离职在即,也没什么事情做,就鼓捣了一下.任意搭建了一个小框架,看看以后能不能搞出自己的一个model,好了.不说别的,上代码 1,先上依赖库 compile 'io.reactivex:rxandro ...

  5. Pygame:编写一个小游戏 标签: pythonpygame游戏 2017-06-20 15:06 103人阅读 评论(0)

    大学最后的考试终于结束了,迎来了暑假和大四的漫长的"自由"假期.当然要自己好好"玩玩"了. 我最近在学习Python,本意是在机器学习深度学习上使用Python ...

  6. python笔记_查看函数调用栈的一个小技巧

    一.背景 最近在看一个开源框架的源码,涉及到的内容非常杂乱,有的函数不知道是在什么时候被谁给调用了?调用的时候传入了什么参数?为了解决这个问题,写了一个小的装饰器. 二.实现 这个装饰器函数主要参考了 ...

  7. Python:通过一个小案例深入理解IO多路复用

    通过一个小案例深入理解IO多路复用 假如我们现在有这样一个普通的需求,写一个简单的爬虫来爬取校花网的主页 import requests import time start = time.time() ...

  8. python中os模块的一些小总结

    (一)os模块的应用小总结 os.name: 获取当前系统平台,Windows下返回'nt',Linux下返回'posix'.   os.linesep: 获取当前平台使用的行终止符.Windows下 ...

  9. Hutool :一个小而全的 Java 工具类库

    Hutool 简介 Hutool 是一个小而全的 Java 工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以"甜甜的 ...

随机推荐

  1. conda和pip加速参考

    conda install和创建虚拟环境下载慢,可以修改/root/.condarc文件: vim /root/.condarc 各系统都可以通过修改用户目录下的 .condarc 文件.Window ...

  2. BUUCTF-佛系少年

    佛系少年 这题我感觉超扯,不知道当时环境是不是断网的,断网咋解密的出来.. 下载后有个压缩包,带加密的,首先16进制看看是否是真加密 这里可以看到,压缩包数据区这里都是未加密的方式 但是到了压缩包目录 ...

  3. 【Nginx】Windows平台下配置Nginx服务实现负载均衡

    前言:废话不多说了,直接上步骤. 系统环境:win10 测试用的开发环境和服务类型:VS2022 + DotNet 6 + WebApi 1.本地先创建一个webapi项目,用于测试使用. 2.新建一 ...

  4. Spring jdbctemplate和事务管理器 全注解配置 不使用xml

    /** * spring的配置类,相当于bean.xml */@Configuration//@Configuration标注在类上,相当于把该类作为spring的xml配置文件中的<beans ...

  5. Python: list列表的11个内置方法

    先来逼逼两句: 在实际开发中,经常需要将一组(不只一个)数据存储起来,以便后边的代码使用.在VBA中有使用数组,可以把多个数据存储到一起,通过数组下标可以访问数组中的每个元素.Python 中没有数组 ...

  6. RT-Thread 组件 FinSH 使用时遇到的问题

    一.FinSH 的移植与使用问题 FinSH组件输入无反应的问题 现象:当打开 finsh 组件后,控制台会打相应的信息,如下图说是: \ | / - RT - Thread Operating Sy ...

  7. 数据结构-二叉树(Binary Tree)

    1.二叉树(Binary Tree) 是n(n>=0)个结点的有限集合,该集合或者为空集(空二叉树),或者由一个根节点和两棵互不相交的,分别称为根节点的左子树和右子树的二叉树组成.  2.特数二 ...

  8. JAVA语言的跨平台性和JDK,JRE与JVM

    Java虚拟机--JVM ~JVM:java虚拟机简称JVM是运行所有java程序的假想计算机,是java程序的运行环境,是java最具有吸引力的特性之一,我们编写的java代码,都运行在JVM之上 ...

  9. Linux 更改家目录下的目录为英文

    export LANG=en_US xdg-user-dirs-gtk-update

  10. c语言编译器介绍

    目录 一.IDE(集成开发环境) 1.windows 编译器 2.Mac中使用 二.环境安装 1.windows安装gcc A.进入安装所在目录,找到MinGW. B.找到我的电脑,右键选择属性. C ...