提问人:user2141238 提问时间:9/16/2023 更新时间:9/16/2023 访问量:25
网络命名空间和 chroot - GUI 应用程序无法启动
Network namespace and chroot - GUI applications don't start
问:
我创建了小型 SUID 应用程序,它应该将 Chromium 与主系统(Arch Linux)隔离开来:
unshare(CLONE_NEWNS|CLONE_NEWCGROUP|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWPID);
mount("none", "/", NULL, MS_PRIVATE|MS_REC, NULL);
chroot("/path/to/new/root");
chdir("/");
mount("proc", "/proc", "proc", MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL);
setresuid(1000, 1000, 1000);
我可以通过以下方式连接到 Xorg 并启动 GUI 应用程序,但是当我尝试隔离网络时:xauth add "$DISPLAY" MIT-MAGIC-COOKIE-1 <hex key>
int namespace_fd = open("/var/run/netns/chromium_netns", O_RDONLY|O_CLOEXEC);
setns(namespace_fd, CLONE_NEWNET);
Chromium 抛出错误:
[2:2:0915/194118.898349:ERROR:ozone_platform_x11.cc(240)] Missing X server or $DISPLAY
[2:2:0915/194118.898364:ERROR:env.cc(255)] The platform failed to initialize. Exiting.
strace:
connect(29, {sa_family=AF_UNIX, sun_path=@"/tmp/.X11-unix/X0"}, 20) = -1 ECONNREFUSED (Connection refused)
connect(29, {sa_family=AF_INET6, sin6_port=htons(6000), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_scope_id=0}, 28) = -1 ECONNREFUSED (Connection refused)
connect(29, {sa_family=AF_INET, sin_port=htons(6000), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 ECONNREFUSED (Connection refused)
我创建网络命名空间并设置 iptables,如下所示:
ip netns add chromium_netns
ip link add veth0 type veth peer name veth1
ip link set veth1 netns chromium_netns
ip addr add 192.168.0.2/24 dev veth0
ip link set dev veth0 up
ip netns exec chromium_netns ip addr add 192.168.0.1/24 dev veth1
ip netns exec chromium_netns ip link set dev veth1 up
ip netns exec chromium_netns ip link set dev lo up
ip netns exec chromium_netns ip route add default via 192.168.0.2
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE
iptables -A FORWARD -i ens33 -o veth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i veth0 -o ens33 -j ACCEPT
Curl 连接到命名空间内部的网络,但 GUI 应用程序无法连接到 Xorg。我的程序的整个源代码(我删除了错误检查):
#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sys/wait.h>
using namespace std;
int main()
{
unshare(CLONE_NEWNS|CLONE_NEWCGROUP|CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWPID);
int namespace_fd = open("/var/run/netns/chromium_netns", O_RDONLY|O_CLOEXEC);
setns(namespace_fd, CLONE_NEWNET);
close(namespace_fd);
int pid = fork();
if (pid != 0) {
setresuid(1000, 1000, 1000);
int status;
waitpid(-1, &status, 0);
return status;
}
mount("none", "/", NULL, MS_PRIVATE|MS_REC, NULL);
chroot("/path/to/new/root/");
chdir("/");
mount("proc", "/proc", "proc", MS_NOSUID|MS_NODEV|MS_NOEXEC, NULL);
setresuid(1000, 1000, 1000);
execlp("/bin/bash", "/bin/bash", NULL);
return 0;
}
答: 暂无答案
评论