“拆解” 应用程序
“拆解” 应用程序
“拆解” 应用程序
“拆解应用程序” 的需求 (1)
实现运行库和应用代码分离
应用之间的库共享
每个程序都需要 glibc
但系统里只需要
一个副本
就可以了
是的,我们可以用 ldd 命令查看
大型项目的分解
改一行代码不用重新链接 2GB 的文件
libjvm.so, libart.so, ...
NEMU: “把 CPU 插上主板”
“拆解” 应用程序
“拆解应用程序” 的需求 (2)
库的
依赖
也是一种代码克隆
震惊世界的
xz-utils (liblzma) 投毒事件
JiaT75 甚至悄悄
绕开了 oss-fuzz
Linux incident
;
Greg Kroah-Hartman revert all commits from umn.edu
;
S&P'21 Statement
如果 Linux 应用世界是静态链接的……
libc 紧急发布安全补丁 → 重新链接
所有
应用
Semantic Versioning
“Compatible” 是个有些微妙的定义
“Dependency hell”
“拆解” 应用程序
实现应用程序的拆解
方案 1: libc.o
在加载时完成重定位
加载 = 静态链接
省了磁盘空间,但没省内存
致命缺点:时间 (链接需要解析很多不会用到的符号)
方案 2: libc.so (shared object)
编译器生成
位置无关代码
加载 = mmap
但函数调用时需要额外一次查表
好处:多个进程映射
同一个
libc.so,内存中只需要一个副本
“拆解” 应用程序
验证 “只有一个副本”
如何实现?
构造一个非常大的 libbloat.so
我们的例子:100M of nop (0x90)
创建 1,000 个进程动态链接 libbloat.so 的进程
观察系统的内存占用情况
100MB or 100GB?
如果是后者,直播会立即翻车;但
out-of-memory killer
会杀死 oom_score 最高的进程
Prototypes are easy. Production is hard. (Elon Musk)
“拆解” 应用程序
推论:初探进程地址空间的实现
地址空间表面是 “若干连续的内存段”
通过 mmap/munmap/mprotect 维护
实际是分页机制维护的 “假像”