我的编程空间,编程开发者的网络收藏夹
学习永远不晚

详解Linux Namespace之User

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

详解Linux Namespace之User

User namespace 是 linux 3.8 新增的一种 namespace,用于隔离安全相关的资源,包括 user IDs and group IDs,keys, 和 capabilities。同样一个用户的 user ID 和 group ID 在不同的 user namespace 中可以不一样(与 PID nanespace 类似)。换句话说,一个用户可以在一个 user namespace 中是普通用户,但在另一个 user namespace 中是超级用户。

User namespace 可以嵌套(目前内核控制最多32层),除了系统默认的 user namespace 外,所有的 user namespace 都有一个父 user namespace,每个 user namespace 都可以有零到多个子 user namespace。 当在一个进程中调用 unshare 或者 clone 创建新的 user namespace 时,当前进程原来所在的 user namespace 为父 user namespace,新的 user namespace 为子 user namespace。

说明:本文的演示环境为 ubuntu 16.04。

创建 user namespace

我们可以通过 unshare 命令的 --user 选项来创建新的 user namespace:


$ unshare -user -r /bin/bash

通过 -r 参数,我们把新的 user namespace 中的 root 用户映射到了外面的 nick 用户(接下来会介绍映射相关的概念)。在新的 user namespace 中,root 用户是有权限创建其它的 namespace 的,比如 utUUJAMOIws namespace。这是因为当前的 bash 进程拥有全部的 capabilities:

下面我们创建一个新的 uts namespace 试试:


$ unshare --uts /bin/bash

我们看到,新的 uts namespace 被顺利的创建了。这是因为除了 user namespace 外,创建其它类型的 namespace 都需要 CAP_SYS_ADMIN 的 capability。当新的 user namespace 创建并映射好 uid、gid 了之后, 这个 user namespace 的第一个进程将拥有完整的所有 capabilities,意味着它就可以创建新的其它类型 namespace。

其实没有必要把上面的操作(创建两个 namespace)分成两步,我们可以通 unshare 一次创建多个 namespace:

在 unshare 的实现中,其实就是传入了 CLONE_NEWUSER | CLONE_NEWUTS,大致如下:


unshare(CLONE_NEWUSER | CLONE_NEWUTS);

在上面这种情况下,内核会保证 CLONE_NEWUSER 先被执行,然后执行剩下的其他 CLONE_NEW*,这样就使得不用 root 用户而创建新的容器成为可能,这条规则对于clone 函数也同样适用。

理解 UID 和 GID 的映射

在前面的演示中我们提到了用户在 user namespace 之间的映射,下面我们同样通过演示来理解映射是什么。我们先查看下当前用户的 ID 和 user namespace 情况:

然后执行 unshare --user /bin/bash 命令创建一个新的 user namespace,注意这次没 -r 参数:


$ unshare --user /bin/bash

在新的 user namespace 中,当前用户变成了 nobody,并且 ID 也变成了 65534。

这是因为我们还没有映射父 user namespace 的 user ID 和 group ID 到子 user namespace 中来,这一步是必须的,因为这样系统才能控制一个 user namespace 里的用户在其他 user namespace 中的权限(比如给其它 user namespace 中的进程发送信号,或者访问属于其它 user namespace 挂载的文件)。

如果没有映射,当在新的 user namespace 中用 getuid() 和 getgid() 获取 user ID 和 group ID 时,系统将返回文件 /proc/sys/kernel/overflowuid 中定义的 user ID 以及 proc/sys/kernel/overflowgid 中定义的 group ID,它们的默认值都是 65534。也就是说如果没有指定映射关系的话,会默认会把 ID 映射到 65534。

下面我们来完成 nick 用户在新的 user namespace 中的映射。

映射 ID 的方法就是添加映射信息到 /proc/PID/uid_map 和 /proc/PID/gid_map (这里的 PID 是新 user namespace 中的进程 ID,刚开始时UUJAMOIw这两个文件都是空的)文件中。这两个文件中的配置信息的格式如下(每个文件中可以有多条配置信息):


ID-inside-ns ID-outside-ns length

比如 0 1000 500 这条配置就表示父 user namespace 中的 1000~1500 映射到新 user namespace 中的 0~500。

对 uid_map 和 gid_map 文件的写入操作有着严格的权限控制,简单点说就是:这两个文件的拥有者是创建新的 user namespace 的用户,所以和这个用户在一个 user namespace 中的 root 账号可以写;这个用户自己是否有写 map 文件的权限还要看它有没有 CAP_SETUID 和 CAP_SETGID 的 capability。注意:只能向 map 文件写一次数据,但可以一次写多条,并且最多只能 5 条。

我们把刚才打开的 shell 窗口称为第一个 shell 窗口开始执行用户的映射操作(把用户 nick 映射为新 user namespace 中的 root)。

第一步,先在第一个 shell 窗口中查看当前进程的 ID:

第二步,新打开一个 shell 窗口,我称之为第二个 shell 窗口。查看进程 3049 的映射文件属性:

用户 nick 是这两个文件的所有者,让我们尝试向这两个文件写入映射信息:

看上去很奇怪呀,明明是文件的所有者,却没有权限向文件中写入内容!其实根本的原因在于当前的 bash 进程没 CAP_SETUID 和 CAP_SETGID 的权限:

下面我们为 /bin/bash 程序设置相关的 capabilities:

复制代码 代码如下:$ sudo setcap cap_setgid,cap_setuid+ep /bin/bash


$ sudo setcap cap_setgid,cap_setuid+ep /bin/bash

然后重新加载 bash,就可以看到相应的 capabilities 了:

现在重新向 map 文件写入映射信息:


$ echo '0 1000 500' > /proc/3049/uid_map
$ echo '0 1000 500' > /proc/3049/gid_map

这次的写入成功了。后面就不需要我们手动写入映射信息了,所以我们通过下面的命令把 /bin/bash 的 capability 恢复为原来的设置:


$ sudo setcap cap_setgid,cap_setuid-ep /bin/bash

第三步,回到第一个 shell 窗口

重新加载 bash,并执行 id 命令:

当前用户已经变成了 root(新的 user namespace 中的 root 用户)。在看看当前 bash 进程具有的 capability:

0000003fffffffff 表示当前运行的 bash 拥有所有的 capability。

第四步,在第一个 shell 窗口中

查看 /root 目录的访问权限:

没权限啊!尝试修改主机的名称:

依然是没有权限啊!看来这个新 user namespace 中的 root 用户在父 user namespace 里面不好使。这也正是 user namespace 所期望达到的效果,当访问其它 user namespace 里的资源时,是以其它 user namespace 中的相应用户的权限来执行的,比如这里 root 对应父 user namespace 的用户是 nick,所以改不了系统的 hostname。

普通用户 nick 没有修改 hostname 的权限,那把默认的 user namespace 中的 root 用户映射为子 user namespace 中的 root 用户后可以修改 hostname 吗?答案是,不行!那是因为不管怎么映射,当用子 user namespace 的用户访问父 user namespace 的资源的时候,它启动的进程的 capability 都为空,所以这里子 user namespace 的 root 用户在父 user namespace 中就相当于一个普通的用户。

User namespace 与其它 namespace 的关系

Linux 下的每个 namespace,都有一个 user namespace 与之关联,这个 user namespace 就是创建相应 namespace 时进程所属的 user namespace,相当于每个 namespace 都有一个 owner(user namespace),这样保证对任何 namespace 的操作都受到 user namespace 权限的控制。这也是为什么在子 user namespace 中设置 hostname 失败的原因,因为要修改的 uts namespace 属于的父 user namespace,而新 user namespace 的进程没有老 user namespace 的任何 capabilities。

以 uts namespace 为例,在 uts_namespace 的结构体中有一个指向 user namespace 的指针,指向它所属的 user namespace(笔者查看的 v4.13内核,uts_namespace 结构体的定义在 /include/linux/utsname.h 文件中):

其它 namespace 的定义也是类似的。

总结

相对其它的 namespace 而言,user namespace 稍显复杂。这是由其功能决定的,涉及到权限管理的内容时,事情往往会变得不那么直观。笔者在本文中也只是介绍了 user namespace 的基本概念,更多丰富有趣的内容还有待大家自行发掘。

参考:

user namespace man page
Namespaces in operation, part 5: User namespaces
Namespaces in operation, part 6: more on user namespaces
Linux capabilities

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

详解Linux Namespace之User

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

详解Linux Namespace之User

User namespace 是 linux 3.8 新增的一种 namespace,用于隔离安全相关的资源,包括 user IDs and group IDs,keys, 和 capabilities。同样一个用户的 user ID 和
2022-06-04

Docker基础知识之Linux namespace图文详解

前言 docker 是“新瓶装旧酒”的产物,依赖于 linux 内核技术 chroot 、namespace 和 cgroup。本篇先来看 namespace 技术。 Docker 和虚拟机技术一样,从操作系统级上实现了资源的隔离,它本质上
2022-06-04

C++命名空间namespace详解

定义命名空间,使用namespace关键字,后面跟命名空间的名字,然后接一对花括号{}即可,{}中即为命名空间的成员,这篇文章主要介绍了C++命名空间namespace,需要的朋友可以参考下
2023-05-14

so加载Linker跟NameSpace机制详解

这篇文章主要为大家介绍了so加载Linker跟NameSpace机制详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-01-15

linux命令之crontab详解

crontab 提交和管理用户的需要周期性执行的任务 更多linux命令详解:linux命令在线工具 Linux 教程:VitePress编写的Linux教程 补充说明 crontab命令 被用来提交和管理用户的需要周期性执行的任务,与wi
2023-08-18

Linux之split命令详解

命令功能:切割文件,将文件以行为单位或以字节为单位进行切割 命令语法: split [?help][?version] split [-<行数>][-l <行数>] [要切割的文件][输出文件名] ,以行数为单位 split [-b <字
2022-06-04

Oracle 创建用户详解(create user)

在Oracle数据库中,可以使用CREATE USER语句来创建新用户。创建用户时,还可以为其指定密码、授予角色、分配表空间等。语法如下:```CREATE USER username IDENTIFIED BY password[DEFA
2023-09-20

Linux驱动之platform总线详解

目录1、platform 总线简介1.1、linux 驱动的分离和分层思想1.1.1、Linux 驱动的分离1.2、platform 平台驱动模型2、platform 框架2.1、platform 总线2.2、platform 驱动2.2.
2022-06-04

Linux命令之mkdir 和 touch详解

目录mkdir什么是 mkdir 命令?如何使用 mkdir 命令?举例说明常用选项参数例子touch什么是 touch 命令?如何使用 touch 命令?举例说明常用选项参数总结mkdir 什么是 mkdir 命令? mkdir 是 ma
2023-06-07

Linux 命令之rsync命令详解

rsync命令rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。rsync使用所谓的“rsync算法”来使本地和远程两个主机之间的文件达到同步,这个算法只传送两个文件的不同部分,而不是每次都整份传送,因此速
2022-06-04

Linux基础命令之mktemp详解

mktemp 创建临时文件或者目录,这样的创建方式是安全的。此命令的适用范围:RedHat、RHEL、Ubuntu、CentOS、SUSE、openSUSE、Fedora。 1、语法 mktemp [选项] [TE
2022-06-04

Linux学习之mkdir命令详解

目录前言1. 文件概念基础知识2. mkdir命令前言 最近几天越来越对linux很感兴趣了, 想再见塔克斯的心情也是越来越浓烈, 自从它给我留了110110110之后,就没了联系。 到现在我也是一头雾水, 我又找不到它而且又没有联
2022-06-04

Linux入门之网络系统详解

目录网络信息修改主机名DNS域名解析网络相关命令防火墙加密算法不可逆加密算法对称加密算法非对称加密算法免密钥登陆日期与时间命令日期同步用户组权限管道和重定向进程网络信息 修改主机名# hostname node01 //本次登录
2022-06-04

编程热搜

目录