解决钉钉Dingtalk无法在Linux新版内核上启动问题-修复可执行栈错误

🕒 阅读时间:5 min read 📝 字数:2195 👀 阅读量: Loading...

本文问题排查与资料整理感谢 AI 协助。

问题描述

最近更新系统到 Linux 内核 7.0 后,发现钉钉无法启动了。运行钉钉时出现以下错误:

Load /opt/apps/com.alibabainc.dingtalk/files/8.1.0-Release.6021101//dingtalk_dll.so failed! Err=/opt/apps/com.alibabainc.dingtalk/files/8.1.0-Release.6021101//dingtalk_dll.so: cannot enable executable stack as shared object requires: Invalid argument

错误很明显:dingtalk_dll.so 无法启用可执行栈

问题分析

这不是钉钉独有的问题,而是glibc 2.41+ 和 Linux 内核新特性共同作用的结果。

什么是可执行栈?

可执行栈是一个老旧的编程技术,它允许程序在栈内存上执行代码。在过去,一些程序和库使用这个技术来实现某些功能(比如动态代码生成、JIT等)。

但是从安全角度来看:

角度评价
安全性可执行栈是危险的:如果攻击者通过缓冲区溢出漏洞控制了程序,他们可以直接在栈上执行恶意代码
现代防护CPU 和操作系统都提供了 NX (No-eXecute) 位技术,默认将栈标记为不可执行,这是基本的安全防护措施

为什么现在才出问题?

这个问题涉及到两个组件的更新,真正的变化来自 glibc 2.41(2024年底发布):

Starting with glibc 2.41, if the kernel rejects making the stack executable, the loader aborts with the error above.

版本行为
glibc 2.41 之前即使内核拒绝了可执行栈请求,glibc 动态链接器会默默忽略错误,继续加载程序
glibc 2.41 之后如果内核拒绝,glibc 会直接报错并中止加载

Linux 内核一直以来都默认开启 NX 保护,拒绝不合理的可执行栈请求。当你的系统升级到新版内核(比如 7.0)时,通常也会同步升级 glibc 到 2.41 以上。这两个变化加在一起,就触发了这个错误。

责任方

钉钉官方。钉钉的 dingtalk_dll.so 在编译时被错误地标记为需要可执行栈(通过 GNU_STACK 段标记)。

这是非常老旧的做法,现代编译器默认不会这样标记,钉钉官方一直没有重新编译打包这个库。不仅仅是钉钉,其他一些闭源软件(比如 NVIDIA HPC SDK 某些版本、一些老游戏)也有同样的问题。

解决方案

解决方案很简单:手动移除 dingtalk_dll.so 的可执行栈标记。两种工具都可以:

方法一:使用 execstack(推荐)

Terminal window
# 安装 execstack 工具
sudo apt update && sudo apt install -y prelink
# 清除可执行栈标记
sudo execstack -c /opt/apps/com.alibabainc.dingtalk/files/8.1.0-Release.6021101/dingtalk_dll.so

方法二:使用 patchelf

Terminal window
# 安装 patchelf 工具
sudo apt install -y patchelf
# 清除可执行栈标记
sudo patchelf --clear-execstack /opt/apps/com.alibabainc.dingtalk/files/8.1.0-Release.6021101/dingtalk_dll.so

两种方法效果相同,都是清除二进制文件中的 GNU_STACK 可执行标记,告诉内核”这个库不需要可执行栈”。修改完成后,重新启动钉钉,就可以正常运行了。

验证

修改完成后,可以用以下命令验证标记是否已经清除:

Terminal window
# 查看当前标记
execstack -q /opt/apps/com.alibabainc.dingtalk/files/8.1.0-Release.6021101/dingtalk_dll.so

如果输出是 - 开头,表示已经没有可执行栈标记了,修复成功。

总结

项目信息
钉钉版本8.1.0.6021101
内核版本7.0.0-10-generic
glibc 版本2.41+
问题库/opt/apps/com.alibabainc.dingtalk/files/8.1.0-Release.6021101/dingtalk_dll.so
错误cannot enable executable stack as shared object requires: Invalid argument

一句话总结:钉钉的 dingtalk_dll.so 被旧工具链标记为需要可执行栈,现代内核出于安全拒绝这个请求,而新的 glibc 2.41 不再容忍这种情况,直接报错导致启动失败。手动清除标记即可解决

希望这篇文章能帮助到遇到同样问题的你!

参考

解决钉钉Dingtalk无法在Linux新版内核上启动问题-修复可执行栈错误

作者:xingwangzhe

本文链接: https://xingwangzhe.fun/posts/dingtalk-linux-fix-execstack/

本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

留言评论