cgexec 无法继承 LD_PRELOAD 环境变量
问题: cgexec 会忽略掉 LD_PRELOAD
的环境变量
有时需要替换malloc库的时候,
我们会使用LD_PRELOAD=/usr/lib64/libtcmalloc.so.4 my_prog
方便地将运行的malloc库替换成tcmalloc.
但是如果使用cgroup来启动my_prog
, 这个环境变量就无法生效了.
验证这个问题, 可以通过一个 test_preload.sh
的脚本:
echo env:
env | grep LD # 显示是否继承了LD_PRELOAD的环境变量.
echo lsof:
lsof -p $$ | grep tcmalloc # 显示是否当前进程加载了tcmalloc
运行:
LD_PRELOAD=/usr/lib64/libtcmalloc.so.4 ./test_preload.sh
> env:
> LD_PRELOAD=/usr/lib64/libtcmalloc.so.4
> lsof:
> test_prel 7588 root mem REG 253,0 301136 36021701 /usr/lib64/libtcmalloc.so.4.4.5
通过cgexec运行时, 没有输出:
LD_PRELOAD=/usr/lib64/libtcmalloc.so.4 cgexec ./test_preload.sh
> env:
> lsof:
说明环境变量没有继承过来. 也没有被加载.
解决方案
使用cgexec时, 必须把环境变量的指定放到cgexec启动之后:
cgexec sh -c 'LD_PRELOAD=/usr/lib64/libtcmalloc.so.4 ./test_preload.sh'
> env:
> LD_PRELOAD=/usr/lib64/libtcmalloc.so.4
> lsof:
> test_prel 10059 root mem REG 253,0 301136 36021701 /usr/lib64/libtcmalloc.so.4.4.5
原因
可执行文件如果设置了capability属性或setuid属性(表示某些只有root级别才有的权限, 网卡抓包等), 就不允许LD_PRELOAD=tcmalloc.so 的环境变量来加载额外的lib, 因为安全性考虑, 不允许任意的代码跑到root身份上运行.
例子:
# ping是设置了网络相关的capability所以普通用户才能抓包.
getcap /bin/ping
> /bin/ping = cap_net_admin,cap_net_raw+p
# 用非root用户运行:
LD_PRELOAD=/usr/lib64/libtcmalloc.so.4 ping baidu.com
# 拿到pid 29841:
lsof -p 29841 | grep tcmalloc
# 啥也没有
# 用root用户运行同样的命令:
LD_PRELOAD=/usr/lib64/libtcmalloc.so.4 ping baidu.com
# 可以看到允许被加载tcmalloc
lsof -p 2256 | grep tcmalloc
> ping 2256 root mem REG 253,0 301136 36021701 /usr/lib64/libtcmalloc.so.4.4.5
同样不允许通过环境变量加载so的属性还有setuid;
setuid属性: 文件被执行时将自己的用户修改为文件所有者的用户, 而不是调用者的.
以及cgexec
How to use cgroup… 文中写的:
They are required to launch, then classify as the application makes use of
LD_LIBRARY_PATH
which is not available when running a binary with setuid (such as cgexec).
总之有机会把任意代码提升权限的事情都不会让做.
使用cgexec加LD_PRELOAD
需要这么做:
# 没有cgexec时:
LD_PRELOAD=/usr/lib64/libtcmalloc.so.4 ./test_preload.sh "a b" "c"
# 使用cgexec时:
cgexec sh -c 'LD_PRELOAD=/usr/lib64/libtcmalloc.so.4 ./test_preload.sh "a b" "c"'
Archive
- 15 Nov 2020 slimarray: gzip的压缩率, 即时访问
- 28 Oct 2020 200行代码实现基于paxos的kv存储
- 18 Oct 2020 后分布式时代: 多数派读写的'少数派'实现
- 20 Dec 2019 Art of Pull Requests(翻译)
- 21 Nov 2019 掐指算算: 你的CDN多花了几百万?
- 19 Nov 2019 一年的素描练习
- 30 Oct 2019 互联网中对象访问频率的91分布
- 09 Jan 2019 哄好面试官系列-1: 比较2个python dict(多级)是否相同
- 04 Nov 2018 存储中的文件合并策略优化
- 27 Sep 2018 软件工程是个面包机
- 26 Aug 2018 程序员必须知道的事情, 一般人我不告诉他
- 16 Aug 2018 cgexec 无法继承 LD_PRELOAD 环境变量
- 04 Aug 2018 mysql group replication实践记录: 步骤, 问题和注意事项
- 13 Feb 2018 枚举所有整勾股数
- 03 Feb 2018 ansible中的include, include_tasks 和 import_tasks 的差别
- 20 Nov 2017 python 并发subprocess.Popen的坑
- 05 Aug 2017 程序员必读: 摸清hash表的脾性
- 06 May 2017 python 进程内存增长问题, 解决方法和工具
- 01 Feb 2017 xp的分布式系统系列教程之: Erasure-Code: 工作原理, 数学解释, 实践和分析.
- 01 Feb 2017 xp的分布式系统系列教程之: Erasure-Code: 工作原理, 数学解释, 实践和分析.
- 11 Nov 2015 可靠分布式系统基础 Paxos 的直观解释
- 28 Jul 2015 socket关闭: close()和shutdown()的差异
- 17 May 2015 随手改变世界之 git-auto-squash
- 17 Feb 2015 Numbers Programmers Should Know About Hash
- 11 Feb 2015 Vim-tabbar: Simple, stupid and fast tab-bar for VIM
- 24 Jul 2014 1% 慢请求优化
- 31 Jan 2014 Some useful resources
- 31 Jan 2014 jobq.py -- Queue processing engine