spa*_*awn 9 linux users root namespace unshare
我正在使用 unshare 来创建每个进程的挂载,它运行得非常好
unshare -m --map-root-user
Run Code Online (Sandbox Code Playgroud)
但是,在创建了我的绑定安装之后
mount --bind src dst
Run Code Online (Sandbox Code Playgroud)
我想将 UID 更改为我的原始用户,以便whoami(和其他人)像echo $USER这样响应我的用户名。
我已经尝试过Simulate chroot with unshare的答案
但是,在做su – user1之后chroot /,我得到
su: Authentication failure
(Ignored)
setgid: Invalid argument
Run Code Online (Sandbox Code Playgroud)
我已经在 Ubuntu 18.04 Beta、Debian stretch、openSUSE-Leap-42.3 上测试过这个。全部都是一样。我猜自从这个答案起作用以来,内核中发生了一些变化。
什么是可行且正确的方法来做到这一点(当然没有真正的根)?
这unshare(1)命令无法做到这一点:
-r, --map-root-用户
[...] 作为一个纯粹的便利功能,它不支持更复杂的用例,例如映射多个 UID 和 GID 范围。
补充组(如有)(video , ...)无论如何都会丢失(或映射到nogroup)。
通过再次更改为第二个新用户命名空间,可以恢复映射。这需要一个自定义程序,因为unshare(1)不会这样做。这是一个非常简约的 C 程序作为概念证明(仅限一个用户:uid/gid 1000/1000,零故障检查)。我们称它为revertuid.c:
#define _GNU_SOURCE
#include <sched.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int fd;
unshare(CLONE_NEWUSER);
fd=open("/proc/self/setgroups",O_WRONLY);
write(fd,"deny",4);
close(fd);
fd=open("/proc/self/uid_map",O_WRONLY);
write(fd,"1000 0 1",8);
close(fd);
fd=open("/proc/self/gid_map",O_WRONLY);
write(fd,"1000 0 1",8);
close(fd);
execvp(argv[1],argv+1);
}
Run Code Online (Sandbox Code Playgroud)
它只是对 所做的映射进行反向映射unshare -r -m,这是不可避免的,以便能够成为 root 并使用mount,如下所示:
$ strace unshare -r -m /bin/sleep 1 2>&1 |sed -n '/^unshare/,/^execve/p'
unshare(CLONE_NEWNS|CLONE_NEWUSER) = 0
open("/proc/self/setgroups", O_WRONLY) = 3
write(3, "deny", 4) = 4
close(3) = 0
open("/proc/self/uid_map", O_WRONLY) = 3
write(3, "0 1000 1", 8) = 8
close(3) = 0
open("/proc/self/gid_map", O_WRONLY) = 3
write(3, "0 1000 1", 8) = 8
close(3) = 0
execve("/bin/sleep", ["/bin/sleep", "1"], [/* 18 vars */]) = 0
Run Code Online (Sandbox Code Playgroud)
所以这给出了:
user@stretch-amd64:~$ gcc -o revertuid revertuid.c
user@stretch-amd64:~$ mkdir -p /tmp/src /tmp/dst
user@stretch-amd64:~$ touch /tmp/src/file
user@stretch-amd64:~$ ls /tmp/dst
user@stretch-amd64:~$ id
uid=1000(user) gid=1000(user) groups=1000(user)
user@stretch-amd64:~$ unshare -r -m
root@stretch-amd64:~# mount --bind /tmp/src /tmp/dst
root@stretch-amd64:~# ls /tmp/dst
file
root@stretch-amd64:~# exec ./revertuid bash
user@stretch-amd64:~$ ls /tmp/dst
file
user@stretch-amd64:~$ id
uid=1000(user) gid=1000(user) groups=1000(user)
Run Code Online (Sandbox Code Playgroud)
或者更短:
user@stretch-amd64:~$ unshare -r -m sh -c 'mount --bind /tmp/src /tmp/dst; exec ./revertuid bash'
user@stretch-amd64:~$ ls /tmp/dst
file
Run Code Online (Sandbox Code Playgroud)
在内核 3.19 之后,行为可能会发生变化,如所示user_namespaces(7):
/proc/[pid]/setgroups文件是在 Linux 3.19 中添加的,但被向后移植到许多早期的稳定内核系列中,因为它解决了安全问题。该问题涉及具有“rwx---rwx”等权限的文件。