标题: 动态链接器符号链接被破坏后的灾难恢复 创建: 2018-09-19 12:02 更新: 2018-09-19 14:11 链接: https://scz.617.cn/unix/201809191202.txt 干了一件蠢事,本意是 $ ln -sf /lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3 但我把src、dst写反了,灾难大片上演。在/sbin、/usr/sbin下疯狂找静态链接的可 用工具,没有。幸亏此时还有一个WinSCP挂在线上。事后吐槽,为啥不把ln这种命令 弄成静态链接的? Debian有个sln(8)的man手册,这是静态版本的ln,不知道sln属于哪个包,没找着。 参看: 16.24 ld.so(8) 16.27 ldconfig(8) 16.28 在Debian上手工升级GLIBC 多年以前手工在线热升级GLIBC时,仔细研究过本质上同一类型的灾难恢复,事隔多 年再次相遇时,居然没能想起从前的文档,真心有点慌了。 很多人碰上过这个问题,今天回顾一下,看有什么可能的应急方案。 $ file -b `which ls` ELF 32-bit LSB pie executable ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=a225fea0f89c5d18c8f0f9c03d7979175f54b7db, stripped $ ldd `which ls` $ LD_TRACE_LOADED_OBJECTS=1 `which ls` $ /lib/ld-linux-armhf.so.3 --list `which ls` linux-vdso.so.1 (0xb6ffd000) libselinux.so.1 => /lib/arm-linux-gnueabihf/libselinux.so.1 (0xb6f79000) libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6e81000) /lib/ld-linux-armhf.so.3 (0xb6fd6000) libpcre.so.3 => /lib/arm-linux-gnueabihf/libpcre.so.3 (0xb6e22000) libdl.so.2 => /lib/arm-linux-gnueabihf/libdl.so.2 (0xb6e0f000) libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xb6dea000) 这三个方案不等价,第二种更普适。 $ ls -l /lib/ld-linux-armhf.so.3 /lib/arm-linux-gnueabihf/ld-2.27.so -rwxr-xr-x 1 root root 105832 Mar 30 03:47 /lib/arm-linux-gnueabihf/ld-2.27.so* lrwxrwxrwx 1 root root 35 Sep 18 16:38 /lib/ld-linux-armhf.so.3 -> /lib/arm-linux-gnueabihf/ld-2.27.so* 这是正常状态。有个在x86上交叉编译得来的ARM版binary用了/lib/ld-linux.so.3, 当前系统中没有/lib/ld-linux.so.3,我想创建同名符号链接,使之指向 /lib/ld-linux-armhf.so.3,但我写错了ln命令: $ ln -sf /lib/ld-linux.so.3 /lib/ld-linux-armhf.so.3 此时ln的src、dst写反了,理解src、dst顺序的最好办法是将ln想像成cp命令。如果 上述命令没有指定-f,情况就会得到控制: $ ln -s /lib/ld-linux.so.3 /lib/ld-linux-armhf.so.3 ln: failed to create symbolic link '/lib/ld-linux-armhf.so.3': File exists 但我不知从什么年代开始养成的坏习惯,习惯性地"ln -sf",这种盲目而过度的自信 属于找抽。现在假设"ln -sf"已经完成,灾难大片上演: $ ls -la /lib -bash: /bin/ls: No such file or directory $ which ls -bash: /usr/bin/which: /bin/sh: bad interpreter: No such file or directory 那些动态链接的binary全歇菜。 如果此时有一个静态链接版busybox在场,可以看到: $ /sbin/busybox-armv8l ls -l /lib/ld-linux-armhf.so.3 lrwxrwxrwx 1 root root 18 Sep 19 11:05 ld-linux-armhf.so.3 -> /lib/ld-linux.so.3 此处不考虑静态链接版busybox在场,不考虑WinSCP在线,不考虑关机离线修复,看 看如何在线热修复。 来,看哥的奇技淫巧: $ LD_LIBRARY_PATH=/lib/arm-linux-gnueabihf LD_HWCAP_MASK=0 /lib/arm-linux-gnueabihf/ld-2.27.so /bin/ls -l /lib/ld-linux-armhf.so.3 lrwxrwxrwx 1 root root 18 Sep 19 11:05 /lib/ld-linux-armhf.so.3 -> /lib/ld-linux.so.3 $ LD_LIBRARY_PATH=/lib/arm-linux-gnueabihf LD_HWCAP_MASK=0 /lib/arm-linux-gnueabihf/ld-2.27.so /bin/ln -sf /lib/arm-linux-gnueabihf/ld-2.27.so /lib/ld-linux-armhf.so.3 $ ls -l /lib/ld-linux-armhf.so.3 lrwxrwxrwx 1 root root 35 Sep 19 11:28 /lib/ld-linux-armhf.so.3 -> /lib/arm-linux-gnueabihf/ld-2.27.so* 很多时候不需要这么复杂的组合,这里只是给了一个较完备的示例。 $ LD_LIBRARY_PATH=/ LD_HWCAP_MASK=0 //<动态链接器>