Bug: mcpp run 下被启动的应用 spawn 子进程(/bin/sh)必然失败 — 私有 glibc 2.44 的 libc.so.6 引用 loader 私有符号
现象
Linux 上 mcpp run 启动 GUI 应用后,应用每 spawn 一次子进程(popen / std::system,底层走 /bin/sh -c)就报:
sh: symbol lookup error: $HOME/.mcpp/registry/data/xpkgs/xim-x-glibc/2.44/lib64/libc.so.6: undefined symbol: __pointer_chk_guard, version GLIBC_PRIVATE
子进程启动即死,popen 拿到空输出。例如应用用 gsettings 探测系统深色主题,结果永远拿不到值。
最小复现(无需具体应用)
GL=$HOME/.mcpp/registry/data/xpkgs/xim-x-glibc/2.44
LD_LIBRARY_PATH="$GL/lib64" /bin/sh -c 'echo hi'
输出:
/bin/sh: symbol lookup error: $HOME/.mcpp/registry/data/xpkgs/xim-x-glibc/2.44/lib64/libc.so.6: undefined symbol: __pointer_chk_guard, version GLIBC_PRIVATE
exit=127
根因
- mcpp 私有 glibc 2.44 的
libc.so.6 里 __pointer_chk_guard 是未定义引用(objdump -T 显示 *UND* (GLIBC_PRIVATE)),该符号只由同版 ld-linux-x86-64.so.2 导出(g DO .data.rel.ro GLIBC_PRIVATE)。
- 系统二进制(如
/bin/sh)由系统 ld.so 加载(本例 Fedora glibc 2.43)。objdump -T /lib64/ld-linux-x86-64.so.2 确认系统 loader 不导出 __pointer_chk_guard。
- 于是当系统二进制通过继承的
LD_LIBRARY_PATH 加载到私有 2.44 libc 时,GLIBC_PRIVATE 符号解析失败 → 进程在启动阶段死掉。
- 私有 glibc 2.39 时代无此问题(
libc.so.6 不引用该 loader 私有符号),是升到 2.44 后的回归。
影响面
mcpp run 会把 LD_LIBRARY_PATH 指到私有 glibc 目录并泄漏给子进程,所以任何在 mcpp 环境里启动、且会 spawn 子进程的应用都会命中:子进程失败、依赖子进程输出的逻辑静默降级。仅影响加载器无关的系统二进制;应用本体通过 PT_INTERP/RUNPATH 用私有 loader 加载,不受影响。
期望行为
mcpp run 不应导致子进程捡到私有 glibc。可考虑:
- 不向子进程泄漏
LD_LIBRARY_PATH(应用本体已靠 PT_INTERP/RUNPATH 加载,子进程清空该变量即可);或
- 私有 glibc 自包含——
libc.so.6 不引用需要同版 loader 才能满足的 GLIBC_PRIVATE 符号,使它在系统 loader 下也可加载。
环境
- 发行版:Fedora(内核 7.1.5-kairiki.finalv2.fc44.x86_64),系统 glibc 2.43
- mcpp:xlings 打包,私有 glibc 2.44(
xim-x-glibc/2.44),mcpp.lock 重新解析后从 2.39 升级而来
Bug:
mcpp run下被启动的应用 spawn 子进程(/bin/sh)必然失败 — 私有 glibc 2.44 的libc.so.6引用 loader 私有符号现象
Linux 上
mcpp run启动 GUI 应用后,应用每 spawn 一次子进程(popen/std::system,底层走/bin/sh -c)就报:子进程启动即死,
popen拿到空输出。例如应用用gsettings探测系统深色主题,结果永远拿不到值。最小复现(无需具体应用)
输出:
根因
libc.so.6里__pointer_chk_guard是未定义引用(objdump -T显示*UND* (GLIBC_PRIVATE)),该符号只由同版ld-linux-x86-64.so.2导出(g DO .data.rel.ro GLIBC_PRIVATE)。/bin/sh)由系统 ld.so 加载(本例 Fedora glibc 2.43)。objdump -T /lib64/ld-linux-x86-64.so.2确认系统 loader 不导出__pointer_chk_guard。LD_LIBRARY_PATH加载到私有 2.44 libc 时,GLIBC_PRIVATE符号解析失败 → 进程在启动阶段死掉。libc.so.6不引用该 loader 私有符号),是升到 2.44 后的回归。影响面
mcpp run会把LD_LIBRARY_PATH指到私有 glibc 目录并泄漏给子进程,所以任何在 mcpp 环境里启动、且会 spawn 子进程的应用都会命中:子进程失败、依赖子进程输出的逻辑静默降级。仅影响加载器无关的系统二进制;应用本体通过PT_INTERP/RUNPATH用私有 loader 加载,不受影响。期望行为
mcpp run不应导致子进程捡到私有 glibc。可考虑:LD_LIBRARY_PATH(应用本体已靠PT_INTERP/RUNPATH加载,子进程清空该变量即可);或libc.so.6不引用需要同版 loader 才能满足的GLIBC_PRIVATE符号,使它在系统 loader 下也可加载。环境
xim-x-glibc/2.44),mcpp.lock重新解析后从 2.39 升级而来