【发布时间】:2020-09-29 19:32:22
【问题描述】:
更新:在继续@kisch 的出色回答,我阅读了有关softirq 上下文的信息,并且似乎(出于非常合理的原因)无法从该上下文中访问用户模式.我认为这确实是它失败的原因。
目前在我处理用户空间文件的内核模块上工作。我知道这被认为是一种不好的做法,但我仍然需要。
该模块使用 netfilter 放置一个钩子来捕获系统中的每个传出数据包,并且在调用该钩子时 - 它调用 filp_open。
巫术从这里开始。
当我从环回发送 ping 时,一切正常,在这种情况下,文件 (/etc/fstab) 已成功打开。
当我从家里的不同 IP ping 机器时,filp_open 失败并显示ENOENT。
为了弄清楚它实际失败的地方,我在 QEMU 仿真上运行了该模块,成功地重现了奇怪的行为。显然,它在内核内部函数do_last 中失败了,在下一个代码中(取自fs/namei.c):
if (unlikely(d_is_negative(path.dentry))) {
path_to_nameidata(&path, nd);
return -ENOENT;
}
我完全不知道是什么导致它失败,因为文件一直存在。
有人知道吗?
这是代码中失败的部分:
unsigned int nf_sendfile_hook(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state)
{
if (NULL == g_get_payload_func) {
// as long as we don't have a way to get our payloads, we don't
// have much to do.
return NF_ACCEPT;
}
struct file *filp;
filp = filp_open("/etc/fstab", O_RDONLY, 0);
if (IS_ERR(filp)) {
printk(KERN_ERR "%p\n", filp);
return NF_ACCEPT;
}
...
}
提前感谢。
【问题讨论】:
标签: c linux-kernel low-level kernel-mode