为了了解 setns(2) 和 unshare(2) 对功能的影响,我创建了以下小型 Python 3 脚本。确保在尝试运行它们之前安装包nsenter
和unshare
( , ...)。pip3 install nsenter
设置(2)
# usernscaps.py: dump all capabilities sets of this process
# when entering a specific (grand)child user namespace.
from nsenter import Namespace
import sys
def dumpcaps(s):
print(s)
with open('/proc/self/status', 'r') as st:
for line in st:
if line.startswith('Cap'):
print(line.rstrip())
if len(sys.argv) != 2:
print('usage: usernscaps.py <PID>')
exit(1)
dumpcaps('initial:')
try:
with Namespace('/proc/%d/ns/user' % int(sys.argv[1]), 'user'):
entered = True
dumpcaps('after setns:')
except PermissionError:
# Switching back to our original user namespace isn't allowed, so ignore the exception.
try:
entered
except NameError:
print('no permission to enter user namespace')
作为一个普通的非特权用户,让我们创建一个新的用户命名空间,该命名空间将归我们所有,并通过睡眠进程保持打开状态(注意:我们将其置于后台):
unshare -U bash -c "readlink /proc/self/ns/user && sleep infinity" &
接下来,usernscaps.py
从上面运行 Python 脚本,并使用 setns(2) 告诉它进入我们新创建的用户空间,然后最后转储能力集:
python3 usernscaps.py $(lsns -t user | grep "infinity" | awk '{ print $4 }')
即使对于我们的非特权用户和进程,这也会在 setns(2) 之后给出:
initial:
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
after setns:
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
这似乎表明 setns(2) 实际上不仅为有效上限提供了全套功能,而且还为允许的上限提供了完整的功能(这是有道理的,因为有效上限在任何时候都必须受到允许的上限的限制) . 不过,它似乎没有补足继承的上限。
克隆(2)
与之前的脚本类似,但这次是 unshare(2)。
# usernsunsharecaps.py: dump all capabilities sets of this process
# upon unsharing the user namespace.
import unshare
import sys
def dumpcaps(s):
print(s)
with open('/proc/self/status', 'r') as st:
for line in st:
if line.startswith('Cap'):
print(line.rstrip())
dumpcaps('initial:')
unshare.unshare(unshare.CLONE_NEWUSER)
dumpcaps('after unshare:')
只需运行它python3 usernsunsharecaps.py
:
initial:
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
after unshare:
CapInh: 0000000000000000
CapPrm: 0000003fffffffff
CapEff: 0000003fffffffff
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
因此,这也在取消共享后在新用户命名空间内提供了完全允许和有效的功能。