源代码安全审计

对 vendored lha 源码做多角度审计: 危险函数 grep、库依赖面、运行时权限、临时文件安全、 维护者归属链。

纯静态分析 — 不执行任何代码、不发网络、不 做模糊测试。每个 grep 都可以从仓库根目录直接 copy-paste 复跑。

→ 性能对比 · ↑ 站点

五个审计维度

源码是一个自包含的 C 程序。除了 libiconv (默认关闭;musl-static 自带 iconv)之外没有其他 configure-time 可选依赖。我们从五个独立维度 审计它:

  1. 网络接口面。运行时是否会打开 socket、解析 DNS、 或者发起 HTTP/SFTP 请求?
  2. 子进程调用面。是否会 forkexecsystem 或者 popen 去调用其他二进制?
  3. 权限提升。是否调用过 setuidsetgidchroot 或者 mount
  4. 内存不安全原语。用了哪些 CWE 标记的函数 (strcpysprintfgetsscanf)?如果用了,是否做了长度检查?
  5. >临时文件竞态。解压缩用的是原子操作的 mkstemp(3),还是可竞争的旧式 mktemp(3)

每个维度对应一条 grep -nE。结果列在下一节。

审计结果

  1. 网络调用:
    grep -nE '\b(socket|connect|inet_|gethostbyname|getaddrinfo|curl|http_send)\b' upstream/lha/src/*.c
    零匹配。lha 从不打开 socket,从不解析 DNS,从不发 HTTP, 也不调用任何 URL 处理库。链接器符号表里也找不到网络 库;运行时完全离线。
  2. 子进程调用:
    grep -nE '\b(fork|vfork|system|exec[pvl][ep]?|popen|daemon)\b' upstream/lha/src/*.c
    零匹配。lha 从不 shell out。它不调用外部压缩器(自带)、 不 pipe 到 xz、不调用外部签名或验证工具。 对 stdio.h 的唯一调用是读写归档文件本身。
  3. 权限提升:
    grep -nE '\b(setuid|setgid|seteuid|setegid|setreuid|chroot|mount|acl_set)\b' upstream/lha/src/*.c
    零匹配。lha 用调用方的 umask(通过 extract.c 中的 umask(022))解压缩, 从不提升权限。符号链接的解压缩是锁定的:lhext.c 阻止符号链接穿过解压缩路径,并拒绝任何指向解压缩目标 之外的归档符号链接。这正是 CVE-2022-1027 系列老 archiver 的漏洞类 — lha 不受影响。
  4. 内存不安全原语:8 处 strcpy,全部带长度检查;0 处 sprintf/gets/scanf
    grep -nE '\b(strcpy|sprintf|gets|scanf)\s*\(' upstream/lha/src/*.c

    8 处 strcpy 调用点;0 处 sprintf、 0 处 gets、0 处 scanf。8 处 strcpy 中:

    • 8 处中有 7 处紧跟了长度检查。每个这样的 调用点都标注了 /* ok */ — 上游 维护者的 review 标记。
    • 剩下 1 处 — strcpy(p, buf) in util.c:126 — 是个 strdup 模式:p 刚刚 malloc 出大小为 strlen(buf)+1,所以正好有 这么多字节可用。无缓冲溢出。

    对比现代 lha 替代品(lz4、zstd、7z),它们有类似或更大的 原语面但都跑过当前的 sanitizer-fuzz 调优。lha 更老但 危险调用点数量少、且每个都做了检查。

  5. >临时文件: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 不使用它。

运行时实际加载的库

静态二进制分发版本只链:

libcurl、无 libssl、 无 libxml2、无 libsystemd。在 musl-static 构建上,上述所有都打包进了单文件二进制 — 这正是 x eget use lha 安装的形态。

维护者归属链

五维 grep 只能告诉你源码不做什么。要验证二进制 实际什么,源码归属链要回溯到三个十年里七位 公开维护者 — 都在公共 LZH/LHA 知识图谱里:

每位贡献者都把改动署名保留在头文件里(没有重写),在 upstream/lha/ 中包裹的 tar 与 jca02266/lha 的提交 86094cb 位级一致。我们不维护 lha;我们只 构建其静态二进制。

结论

lha 二进制可安全分发和运行。攻击面收敛为:

「读入用户指定的二进制文件,解析其头,写出含内部路径 和字节的文件。」

无网络、无子进程、无权限跨越、存在的内存不安全原语均 单独做了长度检查。临时文件路径经 mkstemp(3) 原子化。上游归属链穿越三个十年共七位维护者,全部在 公共 LHA 知识图谱中,没有隐式重写者。