如何修复丢失/重命名的 libc.so.6?

Hao*_*Hao 9 command-line sudo glibc

我需要在不打字的情况下以某种方式成为 root 的原因sudo是因为

error while loading shared libraries: libc.so.6: 
    cannot open shared object file: No such file or directory
Run Code Online (Sandbox Code Playgroud)

我曾经sudosudo mv /lib64/libc.so.6 /lib64/libc.so.6.bak

因为我遵循了一些说明,以便我可以将符号链接更新为libc-12.4.so而不是当前libc-12.2.so

LD_PRELOAD=./libc-2.14.so ln -s ./libc-2.14.so ./libc.so.6
Run Code Online (Sandbox Code Playgroud)

但这不起作用使用sudo. 现在我害怕注销或重新启动系统而死。因为我需要获得 root 权限才能解决这个问题。

我没有救援盘。更糟糕的是,我必须将硬盘安装到另一台机器上并修复它。

请帮忙。

$ sudo bash -c "LD_PRELOAD=./libc-2.14.so ln -s ./libc-2.14.so ./libc.so.6"
sudo: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory

$ LD_PRELOAD=./libc-2.14.so sudo LD_PRELOAD=./libc-2.14.so ln -s ./libc-2.14.so ./libc.so.6
sudo: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory

$ LD_PRELOAD=./libc-2.12.so sudo LD_PRELOAD=./libc-2.12.so ln -s ./libc-2.12.so ./libc.so.6
sudo: error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory

$ LD_PRELOAD=./libc-2.12.so ln -s ./libc-2.12.so ./libc.so.6
ln: creating symbolic link `./libc.so.6': Permission denied
Run Code Online (Sandbox Code Playgroud)

Eli*_*gan 7

您应该只从实时 USB(或 CD/DVD)启动并重命名libc.so.6

LD_PRELOAD不适用于 setuid 可执行文件。但是,如果您愿意,您可以/bin/busybox在重新启动之前进行最后一分钟的备份(不需要以 root 身份运行命令)。可以在没有实时 USB/CD/DVD 的情况下解决此问题,但您仍然需要重新启动,我建议使用一个。


LD_PRELOAD 不适用于 setuid 命令。

当前,您正尝试sudo通过设置来使用重命名的共享库LD_PRELOAD。这是行不通的。您无法更改与sudo链接的共享库LD_PRELOAD,并且它不适用于任何替代方案sudo。如果你做到这一点,那么这将是一个极其严重的安全漏洞。

允许您提升权限的方法sudopkexec(和su)工作是这些可执行文件的 setuid 位设置为0,这导致它们以拥有它们的用户身份运行,对于这些可执行文件,对于这些可执行文件是 root 用户,而不是拥有它们的用户实际上运行它们。当他们运行时,他们会非常仔细地验证您要求他们做什么。这样,只要他们的开发人员足够小心,他们将只允许用户执行他们有权执行的操作。

LD_PRELOAD由其所有者以外的用户运行的 setuid 可执行文件无效这对于安全来说绝对是至关重要的。否则,任何人都可以创建自己的库并强制某个程序sudo使用它,然后任何人都可以获得 root 权限。您可以使用它LD_PRELOAD来运行非 setuid 程序,而 root 可以使用它来运行任何东西。但是,作为一个非root用户,你不能用它来运行这样的程序sudopkexec以及su那些setuid root的。

如果您已经运行了 root shell,则无需重新启动。但是,即使您启用了 root 帐户——也就是说,即使您为它设置了密码,您可以使用它以 root 身份使用类似的命令登录——您su仍然无法在不重新启动的情况下解决问题. 例如su在 Ubuntu 中也需要libc.so.6并且也是 setuid root 所以LD_PRELOAD也不能使用它。1(另见Peter Cordes评论。)

这里的问题是,以 root身份执行操作的可用机制要求您以自己的身份运行 root 拥有的 setuid 可执行文件,但LD_PRELOAD在这种情况下不起作用。如果不是需要以root身份执行操作——或者如果你已经打开了一个 root shell——那么你将能够轻松地将其重命名,而无需重新启动,也无需使用LD_PRELOAD. 这是因为 Ubuntu 系统有/bin/busybox, 静态链接。它允许您运行许多常见的 *nix 工具,包括mvcp命令。您可以运行,也可以运行只是为了获得一个 shell,然后您可以在其中运行命令。跑/bin/busybox mv source destination/bin/busybox sh/bin/busybox没有参数来获取支持的命令列表。它甚至有一个版本dpkg

您可以备份文件(如果需要)并重新启动到实时环境。

我提到这busybox主要是因为,虽然您将无法使用它来获得 root 权限和恢复libc.so.6,但您可以使用它来备份您担心丢失的任何文件,然后再重新启动到实时环境中。我非常怀疑您丢失任何东西,但既然您担心,您可能希望使用它busybox来将任何重要文件(例​​如自上次备份后创建或修改的文档)复制到另一个位置。

以通常的方式重新启动可能不会太远,因为正常关闭实际上涉及运行依赖于libc.so.6. 您可能需要使用Alt+ SysRq+REISUB安全地重新启动。这不是一种理想的关机方式,但它可能比几乎无效的重启尝试和硬重置要好。另一种选择是尝试重新启动,然后尝试使用 REISUB 方法来完成其余的工作。(如果您想关闭机器而不是重新启动机器,请使用 REISU O而不是 REISU B。)

当您从实时环境启动时,重命名文件将很容易。你不需要chroot或做任何花哨的事情。只需挂载您的根文件系统(您通常可以在文件浏览器中单击一下,尽管您可以根据需要使用该mount命令)。然后,在终端中,使用mvorcp命令来恢复libc.so.6. 您将需要sudo,但这在实时环境中运行良好。

我知道你提到你没有救援盘。在无法运行大多数程序的系统上创建可启动的实时 USB 是困难的,也许是不可能的。(你可以busybox用来复制和移动文件,它甚至有一个dd命令,但我不建议你尝试使用它。通常你需要能够以ddroot 身份运行才能创建实时媒体。)也许有人会建议一个方法。如果你有另一台机器来放置硬盘,希望你可以用那台机器创建它。如果没有,最好的办法可能是请熟人做一个。

有一种没有 live CD/DVD/USB 的方法,但您仍然必须重新启动。

然而,存在从外部媒体启动的替代方案。2您仍然需要重新启动,但您不需要实时系统。我不是特别推荐这个,因为它很麻烦;使用实时环境更容易。不过,如果你真的愿意,你也可以在没有人的情况下做到这一点。

正如Zanna之前在评论中指出的那样,救援模式将不起作用,因为大多数程序都需要libc.6.so(例如,/bin/bash提供 shell 的 需要它)。但是您可以通过将引导选项作为引导选项传递给 GRUB 中的内核来使用/bin/busybox shas init引导系统init=/bin/busybox sh3这与获取 root shell的更常见init=/bin/sh(或init=/bin/bash)技术本质上是相同的,但使用/bin/busybox sh而不是常规的/bin/sh,因为它/bin/sh是动态链接的并且需要libc.so.6.

如果您想这样做,请Shift在(重新)引导时按住左键,以便出现 GRUB 引导菜单。(如果Shift不起作用,请使用Esc。)使用箭头键,选择Ubuntu 的高级选项,然后按 Enter。在这一点之后,您将不再按,Enter因为这将正常启动,而不是使用自定义启动选项。选择任何内核并按下e以临时编辑其引导选项。如果有多行且光标不在以 开头的行上linux,请使用箭头键将其移动到那里。添加init=/bin/busybox sh到该行的末尾并按下F10以启动它。

你应该得到一个 BusyBox shell 提示。您必须重新挂载根文件系统 readwrite 并重命名,libc.so.6以便它具有以前的正确名称。为此,请在 BusyBox shell 中运行这些命令(其他libc.so.6位于不同位置的读者必须调整传递给cd命令的目录名称):

mount -o remount,rw /
cd /lib64
mv libc.so.6.bak libc.so.6
Run Code Online (Sandbox Code Playgroud)

然后我建议您将任何缓存的写入同步到文件系统,以只读方式重新挂载,然后重新启动:

sync
mount -o remount,ro /
reboot -f
Run Code Online (Sandbox Code Playgroud)

(没有-f,该reboot命令在这种情况下根本不起作用,因为没有适当的 init 守护程序正在运行。)


0 对于感兴趣的人:当这些程序(如sudo)实际运行您的命令或以 root 或其他替代用户身份创建 shell 时,您的真实用户 ID 和有效用户 ID 均设置为目标用户的 ID。但是,当您运行它们时,在它们执行此操作之前,当它们确定是否应该允许您执行您要求的操作时,它们的有效用户 ID 是 root 的用户 ID,而它们的真实用户 ID 仍然是您的。我提到这一点是为了解决关于真实有效的用户 ID 在程序中的工作方式的常见误解sudo;如果您从未听说过真实有效的用户 ID,请随时忽略此脚注。

1 如前所述,busybox在 Ubuntu 中是静态链接的,不依赖于libc.so.6. 您可能认为您可以使用它来避免重新启动,因为它busybox提供了一个su命令。但是,这没有任何帮助,因为在安装时,busybox它不是 setuid root。要实际工作以允许非 root 用户成为 root,su 必须是 setuid root。有用的功能busybox su是允许root冒充其他用户,而不是允许其他用户冒充root。

2 Zanna 为这个程序做出了巨大贡献,并为它做了所有的测试!

3 即使您可能希望它被解释为后续的内核引导选项,这也会成功传递shbusybox。包括引号会阻止它工作。还要注意的是,在 Ubuntu 中,静态链接的busybox可执行文件只是被称为busybox而不是 busybox-static(尽管提供它的称为busybox-static)。如果您卸载了静态链接的 BusyBox 并安装了动态链接的 BusyBox,则此方法将不起作用,但您不太可能这样做。

  • @Hao `su` 也是 setuid root,就像 `sudo` 和 `pkexec` 一样,并且受到与它们相同的 `LD_PRELOAD` 限制。但我突然想到,如果没有 CD/DVD/USB,虽然最好的方法可能仍然是获得一个,但您可能可以通过将 `init=/bin/busybox sh` 作为 GRUB 中的内核选项引导来解决它。当然,这仍然需要重新启动。我会尝试添加一些关于此的内容。如果我误解了你所说的并且你还没有修复它并且想要关于现在引导到 `busybox sh` 的信息,请告诉我,我可以在我去 afk 之前尝试添加一些关于它的信息。 (3认同)
  • @PeterCordes 是的,`/` 以只读方式启动,但 `busybox` 具有 `mount` 并且重新安装 `rw` 有效。它可以被写入、同步(busybox 有`sync`)、如果需要的话可以重新安装`ro`,虽然busybox 的没有选项的`reboot` 内置在这里不起作用,因为没有适当的init,`reboot -f` 应该。顺便说一句,这是我花这么长时间进行编辑的原因之一。我正在和 Zanna 谈话,她正在测试这个;我目前没有方便测试的方法,但我想扩大我的答案,否则我可能暂时无法回答。到目前为止,测试主要完成,但尚未完全完成。 (2认同)