今天我准备查看socket机制在库函数中的实现,于是下载了glibc的git源代码树。为了便于vscode正确显示语法高亮和代码跳转,我进行了glibc的编译,可以在这里查看方法。(阅读内核代码也类似!)
但是看就看吧,关键在于不知道为什么这么手贱,非要敲下sudo make install。第一次安装以失败告终,都是些我看不懂的报错,我上网查了查也没理解什么意思,索性再次安装,同样的报错又一次出现了。我决定重新编译一下glibc库,结果又产生了同样的报错。这次我察觉到大事不妙。

只有cd这样的内置指令能用,其它所有的依靠/usr/bin的指令全部都不能使用了,都产生清一色的使人绝望的报错。我意识到glibc是整个用户软件体系的根基,但是为时已晚。
然而所有事情都是两面的,这一次灾难虽然给我的Ubuntu带来了潜在的不稳定性,但提高了我对root权限的认识,锻炼了救火能力,同时还让Windows升到了专业版。
1. 用仅剩的几个shell自救
1.1. 尝试差异回退
虽然ls、find这些指令用不了是很让人头疼,但Windows Explorer仍然可用。我可以看到哪些文件是在我脑抽的时候被更改的。不久我便统计出了所有产生差异的文件或文件夹delta.txt:
"\\wsl.localhost\Ubuntu-20.04\usr\lib64"
"\\wsl.localhost\Ubuntu-20.04\usr\include"
"\\wsl.localhost\Ubuntu-20.04\usr\libexec\getconf"
"\\wsl.localhost\Ubuntu-20.04\usr\bin\getent"
"\\wsl.localhost\Ubuntu-20.04\usr\bin\makedb"
"\\wsl.localhost\Ubuntu-20.04\usr\bin\catchsegv"
"\\wsl.localhost\Ubuntu-20.04\usr\bin\pcprofiledump"
...
首先我另开了一个全新完好的WSL2,尝试恢复lib64文件夹下所有文件。新机器下lib64文件夹只有一个ld-linux-x86-64.so.2文件,我知道这个就是动态链接加载器。结果在尝试将这个ld复制回去救火的时候,系统卡住了:

虽然我知道这是win的基操,但我又尝试其它很多办法之后,都无法进行修改,因为还会弹出这样的提示:

1.2. 找可用动态链接/加载器
但是,作为ld,就算不能复制到/usr,复制到~下也勉强可以的吧!先让程序跑起来,什么都好说。ld-linux-x86-64.so.2是符号链接文件,我要找到它指向的文件,就像这样:
new_wsl2$ ls -l /usr/lib64/ld-linux-x86-64.so.2
lrwxrwxrwx 1 root root 32 Apr 15 2020 /usr/lib64/ld-linux-x86-64.so.2 -> /lib/x86_64-linux-gnu/ld-2.31.so
/lib引起了我的注意,它是/usr/lib的符号链接,但后者文件夹不包含在delta.txt中,换言之它下面的文件都完好无损。这可太好了,我先回原机器试试,万一有用呢?
old_wsl2$ /usr/lib/x86_64-linux-gnu/ld-2.31.so ./homo
GOOD TRAP: yarimasune!
很好!点击这里可以查看./homo程序的源代码。起码我可以按类似的方式调用各种程序了——mv、ls等等工具,都能用了。
1.3. 尝试获取root权限
这样的话,我应该可以将ld恢复,然后就不用在调用程序前加这么一个冗长的可用ld的路径。一切都有希望了。
我可以选择重新编译安装glibc,或者执行差异回退,或者用包管理器重装glibc。
但是上面三点都需要一个基本的先决条件:有root权限。首选方法就是sudo,但是结果极其难受:

sudo命令能起作用在于它的执行权限为s而不是x,这使得它执行时可以拥有文件所有者root的权限。然而手动用ld调用sudo,只能获得文件运行者的权限,所以没法执行权限命令。
那可以切换成root用户吧!不过敲下su之后我陷入了沉思。WSL2的root账户初始密码是随机的,这一点极其难受,我之前从来没修改过root密码,所以没法用su命令变更为root用户。
这么一说,我手头只有几个半残的、没有root的shell,还不能创建新shell,这还能做什么事情?我在想能不能通过内核hack技术拿到root,但在不改装内核的情况下想获取root简直是天方夜谭。如果要改装内核,加装或改装模块的话就得用sudo安装,出现循环依赖;改内核映像本身的话,虽然一切皆有可能,但必须要重启,而且还需要学很多东西。
2. 借助有root权限的外援操作磁盘映像
2.1. 确定外援计划
我不愿重启,因为一重启有可能就再也进不去了。但是前面的探索体现出,一切问题的关键在于ld损坏,但要修复ld就只能获取root权限。root权限无法获得,意味着没有任何办法。
不过幸好这是本地的机器,磁盘映像ext4.vhdx可供我任意操作。把它挂到new_machine上,也许就可以修好ld。
2.2. 激活Win11专业版并挂载ext4.vhdx
VHDX是Hyper-V虚拟机的硬盘,可以挂到一般的Linux系统上或WSL2上。对于前者,YouTube上有相关操作视频,不过看起来是只读挂载。对于后者,微软官方给出了操作方法。
第一步执行:
Write-Output "\\.\PhysicalDrive$((Mount-VHD -Path <pathToVHD> -PassThru | Get-Disk).Number)"
但是PS提示没有Mount-VHD这一命令。我一查,这是Hyper-V子系统的命令,要开启它的全部功能,需要Windows 11教育版以上。
那一瞬间我萌生出了花六百多激活专业版的想法。不过……先试试看有没有白嫖的方法?
第一种办法,也是最简单的办法,就是输入激活码,点击查看教程,它需要断网,故Win并没有联机激活,实际上由于激活码无效,也不能联机激活,这时win会各种提醒你激活正版。
也可以只使用第二种办法进行软件破解,点击查看教程。这款软件大概是敏感操作太多,要先按这篇教程的方法关闭安全检查,才能正常下载、解压、执行,否则前面的任何一步都会被Windows检测到,软件也会被迅速扬掉。在完成破解后,一定要记得恢复安全检查功能。
在成功激活专业版后,Hyper-V功能得以顺利启用,vhdx挂载成功。
2.3. 恢复ld
在新WSL2虚拟机上,我执行了如下命令以恢复ld:

第一步是尝试在/lib64下建立符号链接,但ld已经存在了,所以我需要先删去ld。然后再建立链接,这时候提示sudo找不到了?原来是自己脑抽导致梅开二度

在重装了临时的WSL2虚拟机后,我终于修好了ld。之后从临时虚拟机解挂原WSL2的磁盘,顺利地回家。

3. 灾后重建和总结
按网上的建议重装了libc6。虽然一切好像都恢复了正常,但不知道有没有用,可能只是吃个安心药罢了。
综上,我采用在其它Hyper-V虚拟机(此处为另一个WSL2)上挂载vhdx进行救援的方式,恢复了系统的正常运行。只要文件系统没有被破坏,这样的灾难很可能可以救得回来,但根据热力学第二定律,这么一折腾之后系统总是会熵增,产生不确定因素。
这件事故也提醒我们,sudo make install之前一定要三思,不 要 手 贱
4. 后话
可最后我还是把家搬到了原汁原味的Arch Linux
