![如何通过 struct fc_context 获取完整的挂载点路径名](https://linux22.com/image/229755/%E5%A6%82%E4%BD%95%E9%80%9A%E8%BF%87%20struct%20fc_context%20%E8%8E%B7%E5%8F%96%E5%AE%8C%E6%95%B4%E7%9A%84%E6%8C%82%E8%BD%BD%E7%82%B9%E8%B7%AF%E5%BE%84%E5%90%8D.png)
在我的内核模块中,我实现了一个名为 的系统调用挂钩,fsconfig
用于管理与重新挂载只读挂载点相关的操作。例如,如果用户执行,我需要提取钩子内的mount /dev/sda /tmp/mytest -o remount,ro
字符串。/tmp/mytest
fsconfig
为了实现这一目标,我探索了内核fs_context
通过文件描述符访问结构的方法。我的目标是在 fsconfig 系统调用期间通过此结构检索挂载点路径。
最初,我尝试使用dentry_path_raw
从 开始之类的函数fc_context->dentry
,但生成的字符串很简单"/"
,这不能满足我的要求。我还探索了使用d_path
,但它需要一个包含和path
的结构,该结构在系统调用中无法访问,使得这种方法不切实际。dentry
vfsmount
vfsmount
fsconfig
__is_local_mountpoint
最后我在内核源码中发现了这个函数(fs/命名空间.c)。该函数建议通过 current 访问当前任务的命名空间来迭代所有挂载点。我改编了这段代码,将每个挂载点的mnt_root与fs_context根进行比较,成功识别出相应的挂载,代码在这里。
ns = current->nsproxy->mnt_ns;
lock_ns_list(ns);
list_for_each_entry(mnt, &ns->list, mnt_list) {
if (fc->root == mnt->mnt.mnt_root) {
target_dentry = mnt->mnt.mnt_root;
path.dentry = target_dentry;
path.mnt = &mnt->mnt;
break;
}
}
unlock_ns_list(ns);
namespace_sem
然而,对于in namespace.c的使用存在一个重大问题。声明为namespace_sem
static( static DECLARE_RWSEM(namespace_sem);
),意味着模块内部无法直接访问,存在潜在风险。
现在,我的主要问题是:
fs_context
是否有一种安全的方法可以在不需要修改内核代码的情况下获取挂载点路径? (假设fs_context
始终对应于已安装的文件系统。)- 如果我们仅限于迭代挂载点,那么我们如何解决无法安全访问信号量的挑战?
(可以假设内核版本 >= 6.6。)