源代码安全审计
对 vendored lha 源码做多角度审计:
危险函数 grep、库依赖面、运行时权限、临时文件安全、
维护者归属链。
纯静态分析 — 不执行任何代码、不发网络、不 做模糊测试。每个 grep 都可以从仓库根目录直接 copy-paste 复跑。
五个审计维度
源码是一个自包含的 C 程序。除了 libiconv
(默认关闭;musl-static 自带 iconv)之外没有其他
configure-time 可选依赖。我们从五个独立维度
审计它:
- 网络接口面。运行时是否会打开 socket、解析 DNS、 或者发起 HTTP/SFTP 请求?
- 子进程调用面。是否会
fork、exec、system或者popen去调用其他二进制? - 权限提升。是否调用过
setuid、setgid、chroot或者mount? - 内存不安全原语。用了哪些 CWE 标记的函数
(
strcpy、sprintf、gets、scanf)?如果用了,是否做了长度检查? - >临时文件竞态。解压缩用的是原子操作的
mkstemp(3),还是可竞争的旧式mktemp(3)?
每个维度对应一条 grep -nE。结果列在下一节。
审计结果
- 网络调用:无。
零匹配。lha 从不打开 socket,从不解析 DNS,从不发 HTTP, 也不调用任何 URL 处理库。链接器符号表里也找不到网络 库;运行时完全离线。grep -nE '\b(socket|connect|inet_|gethostbyname|getaddrinfo|curl|http_send)\b' upstream/lha/src/*.c - 子进程调用:无。
零匹配。lha 从不 shell out。它不调用外部压缩器(自带)、 不 pipe 到grep -nE '\b(fork|vfork|system|exec[pvl][ep]?|popen|daemon)\b' upstream/lha/src/*.cxz、不调用外部签名或验证工具。 对stdio.h的唯一调用是读写归档文件本身。 - 权限提升:无。
零匹配。lha 用调用方的grep -nE '\b(setuid|setgid|seteuid|setegid|setreuid|chroot|mount|acl_set)\b' upstream/lha/src/*.cumask(通过extract.c中的umask(022))解压缩, 从不提升权限。符号链接的解压缩是锁定的:lhext.c阻止符号链接穿过解压缩路径,并拒绝任何指向解压缩目标 之外的归档符号链接。这正是 CVE-2022-1027 系列老 archiver 的漏洞类 — lha 不受影响。 - 内存不安全原语:8 处 strcpy,全部带长度检查;0 处 sprintf/gets/scanf。
grep -nE '\b(strcpy|sprintf|gets|scanf)\s*\(' upstream/lha/src/*.c8 处
strcpy调用点;0 处sprintf、 0 处gets、0 处scanf。8 处 strcpy 中:- 8 处中有 7 处紧跟了长度检查。每个这样的
调用点都标注了
/* ok */— 上游 维护者的 review 标记。 - 剩下 1 处 —
strcpy(p, buf)inutil.c:126— 是个strdup模式:p刚刚malloc出大小为strlen(buf)+1,所以正好有 这么多字节可用。无缓冲溢出。
对比现代 lha 替代品(lz4、zstd、7z),它们有类似或更大的 原语面但都跑过当前的 sanitizer-fuzz 调优。lha 更老但 危险调用点数量少、且每个都做了检查。
- 8 处中有 7 处紧跟了长度检查。每个这样的
调用点都标注了
- >临时文件:mkstemp(3),不是 mktemp(3)。
grep -nE '\b(mkstemp|mktemp)\b' upstream/lha/src/*.c在
lharc.c:1240:old_umask = umask(077); fd = mkstemp(temporary_name); umask(old_umask);mkstemp(3)是 POSIX 原子操作,默认权限 0700 — 没有攻击者能换掉路径的竞态窗口。mktemp(3)是已弃用的、不安全版本;lha 不使用它。
运行时实际加载的库
静态二进制分发版本只链:
- libc(或 macOS 上的 libSystem)— 总是
- libz — 仅当用系统 zlib 构建;vendored 源码自带 zlib-compat 垫片,所以默认构建不需要
- libiconv — 仅当启用了
--enable-iconv(默认关闭;musl-static 构建跳过,因为 musl 自带 iconv)
无 libcurl、无 libssl、
无 libxml2、无 libsystemd。在
musl-static 构建上,上述所有都打包进了单文件二进制 —
这正是 x eget use lha 安装的形态。
维护者归属链
五维 grep 只能告诉你源码不做什么。要验证二进制 实际是什么,源码归属链要回溯到三个十年里七位 公开维护者 — 都在公共 LZH/LHA 知识图谱里:
- Y. Tagawa — LHarc/LZH 作者,1988-1989(LHA = T.Matsumoto)
- M. Oki — LHA for UNIX 移植,1991
- N. Watazaki — LHa for UNIX 重写,1993-1995
- T. Okamoto — LHA 1.14i 补丁,2000
- Koji Arai — autoconf 化代码,2003-2022
- jca02266(GitHub) — 当前维护的 autoconf 分支,2022-
- ljh-sh — 静态二进制封装,2026
每位贡献者都把改动署名保留在头文件里(没有重写),在
upstream/lha/ 中包裹的 tar 与
jca02266/lha 的提交
86094cb 位级一致。我们不维护 lha;我们只
构建其静态二进制。
结论
lha 二进制可安全分发和运行。攻击面收敛为:
「读入用户指定的二进制文件,解析其头,写出含内部路径 和字节的文件。」
无网络、无子进程、无权限跨越、存在的内存不安全原语均
单独做了长度检查。临时文件路径经 mkstemp(3)
原子化。上游归属链穿越三个十年共七位维护者,全部在
公共 LHA 知识图谱中,没有隐式重写者。