我的目标是在内部学习和了解有关容器如何真正工作的更多信息。
我目前正在运行一个无根的podman容器(以标准用户 ...的身份以podman run -ti ubuntu bash
开头),并且我正在使用nsenter
工具来探索名称空间维度。我的最初目标是一个接一个地“附加”到各种名称空间,并更好地理解它们如何工作。我对安装命名空间有疑问:
我想了解为什么在同时指定-U(用户名空间)和-m(正在使用的用户名)时可以输入名称空间。
nsenter -U -m -t 5903
仅在指定安装名称空间时失败
nsenter -m -t 5903
root@o184i122:~# nsenter -m -t 5903
nsenter: failed to execute bash: Permission denied
使用strace,我发现execve()syscall在nsset()syscall之后得到拒绝的权限...
openat(AT_FDCWD, "/proc/5903/ns/mnt", O_RDONLY) = 3
setns(3, CLONE_NEWNS) = 0
close(3) = 0
execve("/bin/bash", ["-bash"], 0x7fff7d536fa0 /* 31 vars */) = -1 EACCES (Permission denied)
注意:我的主机正在运行ubuntu 20.04、5.4.0-33-通用
更新:我可以复制以下(我相信足够接近)C程序。 小心,我将bash进程的pid硬编码到了podman容器中...
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
void main(void)
{
const char* cmd = "/usr/bin/findmnt";
char *nargv[] = { NULL };
char *nenviron[] = { NULL };
int fd;
struct stat statbuf;
//uncommenting this will make it work//
/*fd=openat(AT_FDCWD, "/proc/5903/ns/user", O_RDONLY);
assert(fd!=-1);
assert(setns(fd, CLONE_NEWUSER)==0);
close(fd);*/
fd=openat(AT_FDCWD, "/proc/5903/ns/mnt", O_RDONLY);
assert(fd!=-1);
assert(setns(fd, CLONE_NEWNS)==0);
close(fd);
assert(setuid(0)==0);
assert(setgid(0)==0);
printf("uid=%d\n",getuid());
printf("gid=%d\n",getgid());
if (stat(cmd, &statbuf)) {
perror("stat failed..");
exit(1);
}
execve(cmd, nargv , nenviron);
}
在不加入用户名称空间的情况下,stat(“ /”)上的权限被拒绝