0

0

Linux进程安全隔离方案_权限与命名空间解析【教程】

冰川箭仙

冰川箭仙

发布时间:2026-01-02 15:11:02

|

105人浏览过

|

来源于php中文网

原创

直接用setuid做进程隔离不安全,因其仅改有效UID而不隔离内核资源视图,无法防止/proc遍历、fd访问、mount泄露、group恢复、资源耗尽等问题;必须配合unshare创建user等命名空间并正确排序,且需补足cgroup、seccomp、capability三方面限制。

linux进程安全隔离方案_权限与命名空间解析【教程】

为什么直接用 setuid 做进程隔离不安全

因为 setuid 只改变有效用户 ID,不隔离内核视角下的资源视图。一旦进程被利用(比如通过 ptrace 或内存泄漏),攻击者仍能遍历 /proc、访问同主机其他进程的文件描述符、甚至挂载新文件系统——它根本没切断命名空间关联。

常见错误现象:sudo -u nobody /usr/bin/python3 -c "import os; print(os.listdir('/proc'))" 依然能看到所有进程 PID 目录;ls /proc/1/fd 在未隔离时可能成功读取 init 进程的打开文件。

  • 仅靠 setuid + chroot 无法防止 mount namespace 泄露(例如攻击者执行 mount --bind /etc /tmp/etc 后逃逸)
  • glibc 的 initgroups() 调用可能意外恢复 supplementary groups,导致权限扩大
  • 没有 cgroup 限制时,恶意进程可耗尽内存或 fork 炸弹拖垮整机

unshare + chroot 组合的关键参数顺序

必须先用 unshare 创建新命名空间,再 chroot 切换根目录。反过来会失败:子进程在旧 mount namespace 中无法真正隐藏宿主文件系统。

典型安全组合命令:

unshare --user --pid --ipc --uts --net --mount --fork \
  --root=/var/chroot/myapp \
  --set-groups=deny \
  --map-root-user \
  /bin/sh -c 'chroot /var/chroot/myapp /bin/sh'

注意点:

  • --map-root-user 是必须的,否则新 user namespace 中 UID 0 不映射到宿主任何 UID,导致 chroot 后连 ls 都因权限拒绝失败
  • --set-groups=deny 阻止子进程调用 setgroups(2),否则可能重新获得额外 group 权限
  • --mount 必须配合 --fork,否则后续 chroot 会因共享 mount namespace 而暴露原根目录

为什么 clone()CLONE_NEWUSER 必须第一个启用

Linux 内核强制要求:如果要创建 user namespace,它必须是第一个被启用的 namespace。否则 clone()unshare() 会返回 EINVAL 错误。

Amazon Nova
Amazon Nova

亚马逊云科技(AWS)推出的一系列生成式AI基础模型

下载

错误示例(shell 中不可见,但 C 程序中常见):

unshare --pid --user  # 失败:EINVAL

正确顺序:

unshare --user --pid --mount --net  # 成功

原因在于:user namespace 是权限降级的锚点,其他 namespace(如 pid、net)的隔离能力依赖于它提供的 UID 映射上下文。没有它,内核无法判断“这个新 PID 1 进程该以谁的身份运行”。

  • 容器运行时(如 runc)内部一定按 CLONE_NEWUSERCLONE_NEWPIDCLONE_NEWNET 顺序调用 clone()
  • 即使只想要网络隔离,也得带上 --user 并做 UID 映射,否则非 root 用户无法安全启用 --net
  • systemd-run 默认不启用 user namespace,所以 systemd-run --scope --property=Delegate=yes ... 不能替代 unshare

真实生产中绕不开的三个补丁点

unshare 方案在生产环境几乎不可用,必须补足三处缺失能力:

  • cgroup v2 接口绑定:用 mkdir /sys/fs/cgroup/myapp && echo $$ > /sys/fs/cgroup/myapp/cgroup.procs 限制 CPU/memory,否则进程仍可抢占全部资源
  • seccomp-bpf 过滤:默认允许全部系统调用,需用 scmp_bpf_compile()crun run --seccomp ... 屏蔽 ptracemountkeyctl 等高危调用
  • capability drop:即使在 user namespace 中,进程默认仍有 CAP_SYS_ADMIN(若未显式丢弃),而该 cap 允许突破 mount/pid namespace 边界

最容易被忽略的是 capability 和 seccomp 的协同:只 drop capability 不过滤 syscalls,攻击者仍可通过 openat(AT_EMPTY_PATH) + ioctl(TIOCGDEV) 探测宿主设备;只上 seccomp 不 drop cap,则某些被允许的 syscall(如 clone(CLONE_NEWNS))仍可新建嵌套 namespace。

相关专题

更多
python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

184

2023.09.27

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

994

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

53

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

238

2025.12.29

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

73

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

25

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

37

2025.11.17

java判断map相关教程
java判断map相关教程

本专题整合了java判断map相关教程,阅读专题下面的文章了解更多详细内容。

32

2025.11.27

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

74

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.4万人学习

Git 教程
Git 教程

共21课时 | 2.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号