使用dlopen,我如何处理我加载的库文件的更改?

kdt*_*kdt 13 c++ linux dlopen

我有一个用C++编写的程序,它使用dlopen加载动态库(Linux,i386,.so).随后修改库文件时,我的程序会崩溃.这是可以理解的,因为可能是文件只是映射到内存中.

我的问题是:除了简单地创建自己的文件副本和dlopening之外,我是否有办法加载一个可以安全防止后续修改的共享对象,或者从我已加载的共享对象的修改中恢复的任何方法?

澄清:问题不是"如何在不破坏程序的情况下安装新库","如果我不控制的人正在复制库,我可以防范吗?"

Dig*_*oss 18

如果您rm在安装新库之前使用库,我认为您的系统将保持分配的inode,文件打开以及程序运行.(当你的程序最终退出时,大多数隐藏但仍然存在的文件资源被释放.)

更新:好的,后澄清.动态链接器通过将MAP_COPY标志(如果可用)传递给,实际上完全"解决"了这个问题mmap(2).但是,MAP_COPYLinux上不存在,并且不是计划的未来功能.第二个最好的是MAP_DENYWRITE,我相信加载器确实使用了,哪个在Linux API中,以及Linux曾经使用过.在映射区域时,它会出错.它应该仍然允许rm并替换.这里的问题是任何对文件具有读访问权限的人都可以映射它并阻止写入,这会打开一个本地DoS漏洞.(考虑一下/etc/utmp.有人建议使用执行权限位来修复此问题.)

你不会喜欢这个,但是有一个简单的内核补丁可以恢复MAP_DENYWRITE功能.Linux仍然具有该功能,它只是在清除位的情况下mmap(2).你必须在每个架构重复的代码中修补它,对于ia32,我相信文件是arch/x86/ia32/sys_ia32.c.

asmlinkage long sys32_mmap2(unsigned long addr, unsigned long len,
                            unsigned long prot, unsigned long flags,
                            unsigned long fd, unsigned long pgoff)
{
        struct mm_struct *mm = current->mm;
        unsigned long error;
        struct file *file = NULL;

        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); // fix this line to not clear MAP_DENYWRITE
Run Code Online (Sandbox Code Playgroud)

只要您没有任何具有凭据的恶意本地用户,这应该没问题.它不是一个远程的DoS,只是一个本地的DoS.


Mar*_*rkR 6

如果安装新版本的库,则正确的过程是在同一目录中创建新文件,然后将其重命名为旧文件.旧文件将在打开时保留,并继续使用.

像RPM这样的程序包管理器会自动执行此操作 - 因此您可以在运行时更新共享库和可执行文件 - 但旧版本仍在运行.

如果您需要采用新版本,请重新启动该过程或重新加载库 - 重新启动过程听起来更好 - 您的程序可以自行执行.甚至init也可以做到这一点.