是否有在库升级期间保护应用程序的机制?

sev*_*evo 10 upgrade dynamic-linking

如果用户在动态链接的应用程序上工作,并且系统正在升级,是否有任何保护机制可以防止应用程序损坏?

还是要看申请?

ilk*_*chu 16

正如@Kusalananda 所提到的,通常升级是通过删除旧文件并创建一个同名的新文件来完成的。这实际上会创建一个带有新 inode 的新文件,只要旧文件处于打开状态,系统就可以自由使用旧文件。

作为一个简化的例子,像

rm /bin/cat
cp /new/version/of/cat /bin/cat
Run Code Online (Sandbox Code Playgroud)

将创建一个逻辑上的新文件,即使cat可能正在运行也可以工作。图书馆也是如此。(以上是一个例子,不是在现实世界中升级文件的可靠方法。)


有人可以尝试就地更改二进制文件,而不是创建一个具有相同名称的新二进制文件。在这种情况下,至少 Linux 实际上会阻止对正在使用的可执行文件进行更改:

window 1 # ./cat
window 2 # echo foobar > cat
-bash: cat: Text file busy
Run Code Online (Sandbox Code Playgroud)

但是,这似乎不适用于动态加载的库...

我制作了一份libc.so.6用于测试的副本,并在使用时用零填充它:

window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ldd ./cat
    linux-vdso.so.1 (0x00007ffcfaf30000)
    libc.so.6 => /tmp/lib/libc.so.6 (0x00007f1145e67000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f1146212000)

window 1 /tmp/lib# LD_LIBRARY_PATH=/tmp/lib ./cat
foo
foo

Segmentation fault
Run Code Online (Sandbox Code Playgroud)

(同时在另一个窗口中,在段错误foo之前,之后)

window 2 /tmp/lib# dd if=/dev/zero of=libc.so.6 bs=1024 count=2000
Run Code Online (Sandbox Code Playgroud)

程序本身实际上对此无能为力,因为我有效地在线编辑了它的代码。

(这可能取决于系统,我在 Debian Jessie 8.5、Linux 3.16.7-ckt25-2+deb8u3 上进行了测试。尤其是 IIRC Windows 系统在防止使用中的文件被修改方面更加积极。)


所以我想答案是升级通常以一种避免任何问题的方式完成,而这得益于文件系统内部结构。但是(在 Linux 上)似乎没有任何保护措施可以防止实际破坏动态库。

  • 我想澄清一下这个答案中的一些内容:在 Unixes 中,如果一个文件被打开并被删除(`rm`),那么它还没有被删除。它将存在于磁盘上,并且仍然可以被所有打开它的进程读取。只有当它的硬链接计数达到零并且文件打开的进动数达到零时才会删除它。 (2认同)