标签: unshare

使用 unshare 模拟 chroot

我正在尝试为最小的源代码 linux 发行版编写引导程序。

我想在一个类似 chroot 的环境中构建。这应该简化包装。在这一点上,我不关心安全性。引导程序不应需要任何非标准的第三方命令。如果不需要 root 那就太好了。

这就是为什么 fakechroot(1) fakeroot(1) chroot(1) 不是我正在寻找的。

是否可以伪造 / 使用 unshare(1) 和 /bin/sh?

chroot not-root-user namespace unshare

13
推荐指数
2
解决办法
5460
查看次数

设置后取消共享 --map-root-user 切换到原始 uid/用户名

我正在使用 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 上测试过这个。全部都是一样。我猜自从这个答案起作用以来,内核中发生了一些变化。

什么是可行且正确的方法来做到这一点(当然没有真正的根)?

linux users root namespace unshare

9
推荐指数
1
解决办法
1877
查看次数

通过添加功能失去权限?

我观察到以下我无法解释的现象。添加CAP_SYS_ADMIN功能后,unshare不再能够写入/proc/self/setgroups.

实际上,写入此文件需要该功能,但这是通过更改用户命名空间来实现的。那么为什么父进程添加功能会阻止写入此文件呢?

me@myhost:~$ unshare -r
root@myhost:~# exit
logout

me@myhost:~$ sudo setcap cap_sys_admin=ep /usr/bin/unshare
me@myhost:~$ unshare -r
unshare: cannot open /proc/self/setgroups: Permission denied

me@myhost:~$ sudo setcap cap_sys_admin= /usr/bin/unshare
me@myhost:~$ unshare -r
root@myhost:~#
Run Code Online (Sandbox Code Playgroud)

顺便说一句:我正在运行内核版本为 4.4 的 Ubuntu 16.04.4 LTS,并且 util-linux(包括unshare)的版本为 2.27.1。

namespace unshare

8
推荐指数
1
解决办法
1286
查看次数

在非共享命名空间内挂载文件系统映像

我正在使用unshare执行诸如将本地绑定安装到某个进程而不需要 root 访问权限之类的操作,例如:

unshare -mr bash mount --bind a b
Run Code Online (Sandbox Code Playgroud)

(是的,这看起来有点愚蠢;在我的实际用例中;unshare正在运行一个执行绑定安装的 bash 脚本。我没有在这里这样做,所以它是一个较小的例子。)

但是,如果我尝试循环安装,它会失败:

ryan@DevPC-LX ~/stuff/util-linux master $ unshare -mr mount -o loop x.img a
mount: no permission to look at /dev/loop<N>
Run Code Online (Sandbox Code Playgroud)

:/

我尝试使用mknod创建一个假循环设备(需要非 root 用户无法使用的权限)、手动运行losetup(仍然需要 root 权限)以及一堆其他不起作用的东西。

当然,我可以这样做chown myuser /dev/loop*,但这似乎可能成为一个主要的安全问题。

此外,guestmount对于我的用例来说太慢了,并且fuseext2有关于写入模式下可能丢失数据的警告(而且它也太慢了)。

有没有办法做到……这个?根本?

mount loop-device namespace unshare

7
推荐指数
2
解决办法
2172
查看次数

为什么基于取消共享的查杀只能与 --fork 一起可靠地工作?

这个答案中我们了解到,您可以通过 Linux PID 命名空间实现对整个进程子树的可靠终止unshare -p

这是我不明白的问题:

  • 仅当我使用-f/--fork选项取消共享时它才有效。

    unshare -fp -- bash -c "watch /bin/sleep 10000 && echo hi"
    
    Run Code Online (Sandbox Code Playgroud)

    当我运行这个时,kill -9那个的PID bash,然后观看,睡眠等都死了,正如我所希望的那样。

  • 但是当我使用它时没有-f

    unshare -p -- bash -c "watch /bin/sleep 10000 && echo hi"
    
    Run Code Online (Sandbox Code Playgroud)

    kill -9bash PID,然后将其watch重新设置为PID 1(在我的Ubuntu上是systemd),所以我没有达到杀死所有孩子的预期效果。

问题:

  • 为什么--fork必须要达到预期的效果?为什么不unshare使用exec()fork 还不够?
  • 有解决方法吗?我更希望能够方便地发送到通过开始杀死其下面的所有内容kill -9而创建的 PID 。unshare但是当我使用 时--fork,杀死我开始时返回的 pidunshare将简单地杀死unsharebash …

process kill namespace unshare

7
推荐指数
1
解决办法
1885
查看次数

如何阻止进程写入 systemd 日志?

我正在使用第三方 .NET Core 应用程序(VS Code 扩展使用的二进制发行版),不幸的是,该应用程序启用了诊断日志记录,但没有明显的方法来禁用它(我已经向作者报告了这一点)。理想的解决方案(除了能够禁用它之外)是,如果我可以指定 systemd 它不应该为该特定程序记录任何内容,但我一直无法找到任何方法来执行此操作。这是迄今为止我尝试过的所有内容:

我尝试的第一件事是重定向stdoutstderr/dev/null: dotnet-app > /dev/null 2>&1。这确实禁用了任何正常输出,但诊断日志记录仍在写入 systemd 日志。

我希望应用程序有一个命令行参数,允许我禁用诊断日志记录。它确实有一个冗长的参数,但经过实验,它似乎只对正常输出有影响,对诊断日志记录没有影响。

通过使用strace并查找对 的调用connect,我发现应用程序将诊断日志直接写入到/dev/log.

该路径/dev/log是 的符号链接/run/systemd/journal/dev-log,因此为了验证我的发现,我将符号链接更改为指向/dev/null。这确实阻止了诊断日志记录出现在 systemd 日志中。

有人告诉我LD_PRELOAD并制作了一个库,connect用我自己的版本替换了标准,在尝试连接到/dev/log. 这在我的测试程序中工作正常,但在 .NET Core 应用程序中失败,在connect ENOENT /tmp/CoreFxPipe_1ddf2df2725f40a68990c92cb4d1ff1e. 我尝试了我的库,但即使我所做的只是直接将参数传递给标准connect函数,它仍然会失败并出现相同的错误。

然后,我尝试使用 Linux 命名空间来实现它,以便仅/dev/log指向/dev/null.NET Core 应用程序:unshare --map-root-user --mount sh -c "mount --bind /dev/null /dev/log; dotnet-app $@". …

gdb unix-sockets ld unshare systemd-journald

6
推荐指数
1
解决办法
2124
查看次数

时间命名空间应该如何使用?

我想我可以做这样的事情:

\n
sudo unshare -T bash -c \'date -s "$1" && foobar\' sh "$(date -d -1day)"\n
Run Code Online (Sandbox Code Playgroud)\n

所以foobar会看到与系统其他部分不同的系统时间。但是,似乎不包含系统时间的变化。它改变了整个系统的系统时间。

\n

这篇 LWN 文章似乎表明这个命名空间是为了我试图赋予它的用途而设计的。

\n
\n

当在根时间命名空间之外调用时,调整系统时间的系统调用将调整特定于命名空间的偏移量。

\n
\n

看着strace date -s ...,我看到了其他输出:

\n
clock_settime(CLOCK_REALTIME, {tv_sec=1619044910, tv_nsec=0}) = 0\n
Run Code Online (Sandbox Code Playgroud)\n

然而,阅读time_namespaces(7)

\n
\n

这会影响针对这些时钟进行测量的各种 API,包括:clock_gettime(2)、clock_nanosleep(2)、nanosleep(2)、timer_settime(2)、timerfd_settime(2) 和 /proc/uptime。

\n
\n

我看到它没有提到clock_settime(2)。“包括”一词告诉我这可能不是完整的列表,但也许是。

\n

我也不懂--boottime/ --monotonic。看着clock_settime(2),我看到:

\n
\n

CLOCK_MONOTONIC 不可设置的系统范围时钟,表示自 \xe2\x80\x94 以来的单调时间,如 POSIX\xe2\x80\x94 所描述的“过去的某个未指定点”。在 Linux 上,该点对应于系统自启动以来运行的秒数。

\n
\n
\n

CLOCK_BOOTTIME(自 Linux …

linux clock namespace unshare

6
推荐指数
1
解决办法
1544
查看次数

如何检查 Linux 主机上的 cgroup 是否可用?

是否有命令可以检查容器服务是否在 Linux 系统上运行?有人建议,unshare但我不确定这是否是最好的方法。

linux cgroups containers unshare

5
推荐指数
1
解决办法
1万
查看次数

为什么我不能将挂载命名空间绑定到文件

我观察到以下几点:

作为 1 号 shell 中的非特权用户:

user@box:~$ sysctl kernel.unprivileged_userns_clone
kernel.unprivileged_userns_clone = 1
user@box:~$ unshare --mount --user
nobody@box:~$ echo $$
18655
Run Code Online (Sandbox Code Playgroud)

并作为 2 号 shell 中的 root:

root@box:~# mkdir -p /tmp/myns
root@box:~# touch /tmp/myns/{user,mnt}
root@box:~# mount --bind /proc/18655/ns/user /tmp/myns/user 
root@box:~# mount --bind /proc/18655/ns/mnt /tmp/myns/mnt
mount: /tmp/myns/mnt: wrong fs type, bad option, bad superblock on /proc/18655/ns/mnt, missing codepage or helper program, or other error.
Run Code Online (Sandbox Code Playgroud)

该错误令人惊讶:我无法将挂载命名空间绑定挂载到文件,但我可以将用户命名空间绑定挂载到文件?为什么会这样,我怎样才能使这个挂载命名空间可供非特权用户使用user

为什么我想要这个:为了测试一个程序,我想~user用一个临时文件系统覆盖,最初共享原始内容。可以按照以下方式由 root 设置

tmp='/tmp/GAtcNNeSfM8b'
mkdir -p "$tmp"
mount -t tmpfs -o size=100m …
Run Code Online (Sandbox Code Playgroud)

linux namespace bind-mount unshare

5
推荐指数
1
解决办法
709
查看次数

如何在网络命名空间中使用绑定挂载?

我有一个在网络命名空间中运行的应用程序。这效果很好。

我想在不同的命名空间中多次运行该应用程序。为了方便起见,我想将应用程序的工作目录绑定到命名空间内的 /tmp/nsX 之类的目录。

如果我只是mount --bind /tmp/nsX /var/lib/my-app在命名空间中执行此操作,那么当我退出命名空间时,挂载就会消失。

通过进入/退出命名空间,我的意思是ip netns exec bash

我正在看unsharensenter但我不知道该怎么做。

我想要:

  • 为命名空间配置网络
  • 在命名空间中为我的应用程序的工作目录创建绑定安装。
  • 在命名空间中生成我的应用程序。如果有帮助的话,它有一个“fork”选项。
  • 能够离开和进入命名空间,而不会出现任何东西消失或消失的情况。

如果我需要使用其他一些命名空间类型,那也没有问题。

namespace network-namespaces unshare

4
推荐指数
1
解决办法
1765
查看次数

当使用 --fork 表示 `nsenter -t &lt;pid&gt;` 时,如何获取 `unshare` 的子 pid?

使用 时unshare --pid --fork,该nsenter命令必须附加到子 pid 而不是unsharepid 以获取正确的 pid 命名空间。

我可以按如下方式获取 unshare 的 pid:

unshare --pid --mount --fork --mount-proc  bash & 
echo PID: $!
fg
Run Code Online (Sandbox Code Playgroud)

但我需要unshare孩子的 pid (2914003) 才能输入正确的命名空间:

ps wwfuax | grep -A1 unshare 
2914002 pts/4    S      0:00  |           \_ unshare --pid --mount --fork --mount-proc bash
2914003 pts/4    S+     0:00  |               \_ bash
Run Code Online (Sandbox Code Playgroud)

这有效:nsenter -t 2914003 这不起作用:nsenter -t 2914002

我希望有某种选择,unshare --show-child-pid但没有。

获取取消共享子进程 pid 的可靠可靠方法是什么?

linux namespace unshare

4
推荐指数
1
解决办法
785
查看次数

为什么 unshare -p 并不意味着 -f 和 --mount-proc?

手册页指定你可能会感兴趣的使用--fork--mount-proc创建PID命名空间的时候,偏偏这些选项不是默认?

process namespace unshare

0
推荐指数
1
解决办法
791
查看次数