为什么 UTS 命名空间隔离不起作用?

为什么 UTS 命名空间隔离不起作用?

1. 在单独的子UTS命名空间下启动shell进程

sudo unshare -f --mount-proc -u /bin/bash

2.在此过程中更改主机名

hostnamectl set-hostname newhostname

3.从不同的shell监视变化

$ hostname
newhostname

预期结果

该进程在父命名空间中保留其旧主机名。

结果得到

更改新 UTS 命名空间中的主机名也会更改父命名空间中的主机名。


为什么会发生这种情况?我使用的是 Ubuntu 20.04,内核版本 5.10.23-xanmod1 ( uname -r)。

答案1

hostnamectl随之而来的是系统环境并且它不执行sethostname(2)系统调用。它问系统通过套接字来做到这一点/run/dbus/system_bus_socket。作为系统没有更改命名空间,它在初始命名空间中执行此操作,将旧UTS命名空间的名称(运行时的初始名称)更改为提供的新名称,并保留新UTS命名空间的名称不变(与OP的声明相反) :旧主机名。还会有其他副作用,例如文件/etc/hostname被更改。

这可以使用 检查strace。里面没有sethostname(2),但是有可见的 systemd 相关元素:

newfstatat(AT_FDCWD, "/run/systemd/system/", {st_mode=S_IFDIR|0755, st_size=40, ...}, AT_SYMLINK_NOFOLLOW) = 0

如果阻止上面的调用成功(通过使用然后用 aunshare -f -u -m /bin/bash将其全部覆盖),则会得到:/runmount -t tmpfs tmpfs /run

System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

该对话框稍后通过打开的套接字完成,如下所示:

connect(3, {sa_family=AF_UNIX, sun_path="/run/dbus/system_bus_socket"}, 30) = 0

hostname在这种环境中,应该使用用于读取的低级“legacy”命令或者更改主机名。它确实直接调用sethostname(2)系统调用:它将更改新的 UTS 命名空间的名称,并保持旧的(初始)UTS 命名空间不变:

hostname newhostname

为了hostnamectl影响新的 UTS 命名空间(就像使用 LXC 启动的完整容器一样),这需要的不仅仅是一个unshare命令:一个全新的 UTS 实例系统生态系统必须存在于新环境中,可能需要输入/取消共享几个其他名称空间以及许多额外的样板文件。

相关内容