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

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

我需要以某种方式成为 root 而无需输入的原因sudo是因为

error while loading shared libraries: libc.so.6: 
    cannot open shared object file: No such file or directory

我曾经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

但是使用 不起作用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

答案1

您应该从实时 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 权限。您可以使用它来运行非 setuid 程序,root 可以使用它来运行几乎任何东西。但作为非 root 用户,您不能使用它来运行setuid root 的LD_PRELOAD程序,例如sudopkexec和。su

如果你已经如果有 root shell 正在运行,则无需重新启动。但即使启用了 root 帐户(即,即使为其设置了密码,可以使用以下命令以 root 身份登录),您仍无法在不重新启动su的情况下解决问题。例如,su在 Ubuntu 中也需要libc.so.6并且也是 setuid root,因此LD_PRELOAD也无法使用它。1(也可以看看彼得·科德斯评论

这里的问题是,执行操作的可用机制以 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/busyboxdpkg

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

我之所以提到这一点busybox,主要是因为,虽然你不能使用它来获取 root 权限并恢复libc.so.6,但你在重新启动进入实时环境之前,使用它来备份您担心丢失的任何文件。我非常怀疑你失去任何东西,但由于您担心,您可能需要使用busybox将任何重要文件(如自上次备份以来创建或修改的文档)复制到另一个位置。

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

当您从实时环境启动时,重命名文件将很容易。您不需要chroot做任何花哨的事情。只需挂载您的根文件系统(通常只需在文件浏览器中单击一下即可完成,但mount如果您愿意,也可以使用命令)。然后,在终端中,使用mvcp命令恢复libc.so.6。您需要sudo,但这在实时环境中可以正常工作。

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

有一种方法不需要实时 CD/DVD/USB,但是您仍然必须重新启动。

然而,从外部媒体启动的替代方法。2您仍然需要重新启动,但您不需要实时系统。我并不特别推荐这样做,因为它很麻烦;使用实时环境更容易。您但是,如果你真的愿意的话,可以不用它。

作为扎娜之前在评论中指出,救援模式无法工作,因为大多数程序都需要它libc.6.so(例如,提供 shell 的 需要它)。但你可以使用as/bin/bash来引导系统/bin/busybox sh在里面通过init=/bin/busybox sh作为启动选项传递给 GRUB 中的内核。3这本质上与更常见的init=/bin/sh(或init=/bin/bash)获取 root shell 的技术相同,但是使用/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 提示。您必须重新挂载根文件系统读写并重命名,libc.so.6以便它具有以前的正确名称。为此,请在 BusyBox shell 中运行以下命令(其他位于libc.so.6不同位置的读者必须调整传递给cd命令的目录名称):

mount -o remount,rw /
cd /lib64
mv libc.so.6.bak libc.so.6

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

sync
mount -o remount,ro /
reboot -f

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


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

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

2 Zanna 为这一过程做出了巨大贡献,并且全部测试它!

3 尽管您可能希望将其解释为后续的内核启动选项,但此命令仍成功传递shbusybox。包含引号会阻止其工作。还请注意,在 Ubuntu 中,静态链接的busybox可执行文件仅称为busybox不是 busybox-static(尽管包裹提供它称为busybox-static)。如果你已经卸载了静态链接的 BusyBox 并安装了动态链接的 BusyBox,那么此方法将不起作用,但你这样做的可能性很小。

答案2

我知道 root 密码,所以应该有办法让我打开 root shell,但似乎我不能。

getty您不能使用 root 密码,因为(通过重命名 libc)您破坏了可以使用它的所有“正常”方式,包括在另一个文本控制台上登录。如果你有静态链接的 su 或 sudo,你可以用它来运行busybox mv,或者(在获得一个有效的 root shell 的一般情况下),使用

LD_PRELOAD=whatever LD_LIBRARY_PATH=whatever static-su --preserve-environment将此自定义环境传递给以 root 身份运行的 bash

Setuid 二进制文件本身不能信任运行它们的用户提供的环境,但(如果它们工作的话)可以传递环境如果您请求了该操作,并且您知道正确的密码来验证该操作。

但是由于你没有静态 setuid 二进制文件来验证你的请求,以便将自定义环境传递给以root,您应该只使用您的物理访问权限重新启动到允许您修改根 FS 的环境。例如 DVD 或 USB 记忆棒,或使用其启动您的常规系统init=/bin/busybox sh(参见@Eliah 的回答)。

如果你手头没有恢复介质,请在另一台计算机上创建可启动文件,使用 Ubuntu Live 映像或适用于修复各种操作系统和运行硬件诊断程序的多个恢复启动映像之一 (以下是对 5 种不同产品的评价)(这些通常比实时的 Ubuntu 要小,例如在 USB 上仅占用约 700MB 的空间。)

您可以使用其中一个(或 Ubuntu)设置一个可启动的 USB 棒,同时仍能将其用于普通文件存储;您无需将整个 USB 棒专用于可启动映像。(不过,创建实时 USB 棒的最简单方法会清除之前的内容,有时甚至无法将其用于存储文件。)


另一个选择是让 initramfs 进入 shell在执行内核命令行上传递的命令之前pivot_rootinit=这不依赖于根文件系统本身的任何内容。您可能根本没有编辑器,但您有cat重定向,以及 mv 和 ln。(cat > /mnt/root/etc/something)。如果您需要修复的问题并不简单,您可能应该启动更强大的东西!

在某些启动失败的情况下会自动发生这种情况,例如,如果 RAID 检测失败或出现其他情况,则根文件系统首先不会挂载(甚至是只读)。(Ubuntu 15.10-每次启动时都会出现“BusyBox 内置 shell(initramfs)”

break=bottom你可以在内核命令行上实现它在完成大部分工作(加载模块和以只读方式挂载根文件系统)之后,但在执行实际操作之前,进入 initramfs 中的 busybox shell initbreak=premount提前停止;请参阅该链接或/usr/share/initramfs-tools/init了解更多详细信息。

答案3

我在 elementary OS 上解决了这个问题,方法是制作一个包含我拥有的 elementary OS 版本的可启动驱动器,然后实时启动它。

启动 liveusb 后,我将文件夹 /lib 复制到有故障的 elementary OS /lib 文件夹,并通过保留最近的文件进行合并。

这对我来说很管用。希望对你也一样。

答案4

我将“libc.so.6”重命名为“libc.so.6_old”,但仍然遇到同样的问题,因此我们几乎没有选择。我们可以通过 3 种方式解决此问题(我在集群上,因此我有一个共享路径,即所有用户和其他节点的主目录)

(前两个选项仅当您已经是 root 用户,并且没有注销或退出时才有效)

  1. 当它改变时我们已经处于 root 用户,并开始面临以下错误:

ls:加载共享库时出错:libc.so.6:无法打开共享对象文件:没有此文件或目录

然后不要从 root 用户注销,否则您将无法切换用户,然后只有第三个选项可用。首先,取消设置所有默认设置路径

#取消设置库路径

#取消设置 LD_LIBRARY_PATH

#取消设置路径

然后仅设置以下路径,并运行最后一个命令,该命令将再次为 libc.so.6 创建软链接。

#导出 PATH=/usr/bin:/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

#导出 LIBRARY_PATH=/usr/lib

#导出 LD_LIBRARY_PATH=/usr/lib

#ldconfig

  1. 现在在第二个选项中你也应该以 root 身份运行,如果不是那么它将不起作用。如果你是 root 并且无论如何“ldconfig”都不会那么尝试以下,

#取消设置库路径

#取消设置 LD_LIBRARY_PATH

#取消设置路径

然后仅设置以下路径,复制临时目录中的所有“lib64”,并进行相同的更改

#导出 PATH=/usr/bin:/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

#导出 LIBRARY_PATH=/usr/lib

#导出 LD_LIBRARY_PATH=/usr/lib

#cp -prv /usr/lib64 /tmp/。

#mv /tmp/lib64/libc.so.6_old /tmp/lib64/libc.so.6 ---或--- #ln -s /tmp/lib64/libc-2.XX.so /tmp/lib64/libc.so.6

#导出 LIBRARY_PATH=$LIBRARY_PATH:/tmp/lib64

#导出 LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/tmp/lib64

#mv /usr/lib64/libc.so.6_old /user/lib64/libc.so.6 ---或--- #ln -s /usr/lib64/libc-2.XX.so /usr/lib64/libc.so.6

  1. 现在,如果上述选项均不起作用或不可用,或者您已丢失连接,请按照以下步骤操作,
  • 强制关闭机器电源。
  • 使用任何实时操作系统(例如 Suse、Mint、Puppy、Kali)创建实时操作系统磁盘/驱动器/U盘
  • 从实时操作系统启动,并打开本地磁盘。现在显示为媒体或其他存储设备。
  • 复制——或者——重命名第二个选项最后阶段中提到的“libc.so.6”并重新启动机器(删除实时操作系统源/媒体并以正常模式启动)。

相关内容