尝试使用bwrap沙盒化微信遇到的问题

安装了AUR的wechat-bin包,它提供了/opt/wechat/wechat,我正在尝试用bwrap沙盒化它。但是在启动它时遇到了动态链接库无法加载的问题。

使用的脚本如下

/usr/bin/bwrap 
--unshare-cgroup 
--symlink usr/lib /lib 
--symlink usr/lib /lib64 
--ro-bind /usr/lib /usr/lib 
--ro-bind /usr/bin /usr/bin 
--ro-bind /run /run 
--ro-bind /etc /etc 
--ro-bind /usr/share /usr/share 
--ro-bind /run /run 
--ro-bind /opt /opt 
/opt/wechat/wechat

然后就会报错, /opt/wechat/wechat: error while loading shared libraries: libandromeda.so: cannot open shared object file: No such file or directory,而不使用bwrap直接运行时没有报错。我又双叒叕少bind了什么东西呢?

虽然我感觉以下这些尝试都没啥用,但是为了防止有人说我没有努力还是贴一下:

我尝试将脚本最后一行的/opt/wechat/wechat改为/usr/bin/bash后问题消失了,于是我怀疑是wechat链接了奇怪的库,于是我检查了ldd /opt/wechat/wechat以及readelf -d /opt/wechat/wechat,结果发现wechat链接了自身目录的某些动态链接库。

[xtricman@DESKTOP-BFOE35J ~]$ ldd /opt/wechat/wechat
        linux-vdso.so.1 (0x00007f8f15c8f000)
        libglib-2.0.so.0 => /usr/lib/libglib-2.0.so.0 (0x00007f8f15afb000)
        libatomic.so.1 => /usr/lib/libatomic.so.1 (0x00007f8f15af0000)
        libXcomposite.so.1 => /usr/lib/libXcomposite.so.1 (0x00007f8f15aeb000)
        libXrender.so.1 => /usr/lib/libXrender.so.1 (0x00007f8f15adf000)
        libXrandr.so.2 => /usr/lib/libXrandr.so.2 (0x00007f8f15ad2000)
        libudev.so.1 => /usr/lib/libudev.so.1 (0x00007f8f0d5b8000)
        libX11.so.6 => /usr/lib/libX11.so.6 (0x00007f8f0d474000)
        libXext.so.6 => /usr/lib/libXext.so.6 (0x00007f8f0d460000)
        libXtst.so.6 => /usr/lib/libXtst.so.6 (0x00007f8f0d458000)
        libXdamage.so.1 => /usr/lib/libXdamage.so.1 (0x00007f8f0d453000)
        libXfixes.so.3 => /usr/lib/libXfixes.so.3 (0x00007f8f0d44b000)
        libgssapi_krb5.so.2 => /usr/lib/libgssapi_krb5.so.2 (0x00007f8f0d3f8000)
        libandromeda.so => /opt/wechat/libandromeda.so (0x00007f8f0ce00000)
        libconfService.so => /opt/wechat/libconfService.so (0x00007f8f0ca00000)
        libilink2.so => /opt/wechat/libilink2.so (0x00007f8f0c600000)
        libilink_network.so => /opt/wechat/libilink_network.so (0x00007f8f0ba00000)
        libilink_protobuf.so => /opt/wechat/libilink_protobuf.so (0x00007f8f0b600000)
        libowl.so => /opt/wechat/libowl.so (0x00007f8f0b200000)
        libvoipChannel.so => /opt/wechat/libvoipChannel.so (0x00007f8f0ae00000)
        libvoipCodec.so => /opt/wechat/libvoipCodec.so (0x00007f8f08800000)
        libvoipComm.so => /opt/wechat/libvoipComm.so (0x00007f8f08400000)
        libmmmojo.so => /opt/wechat/libmmmojo.so (0x00007f8f08000000)
        libz.so.1 => /usr/lib/libz.so.1 (0x00007f8f0d3db000)
        libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f8f0d3d6000)
        libxkbcommon.so.0 => /usr/lib/libxkbcommon.so.0 (0x00007f8f0c9a3000)
        libxkbcommon-x11.so.0 => /usr/lib/libxkbcommon-x11.so.0 (0x00007f8f0d3ca000)
        libxcb-glx.so.0 => /usr/lib/libxcb-glx.so.0 (0x00007f8f0cde3000)
        libxcb-xkb.so.1 => /usr/lib/libxcb-xkb.so.1 (0x00007f8f0c5e1000)
        libxcb-randr.so.0 => /usr/lib/libxcb-randr.so.0 (0x00007f8f0cdd1000)
        libxcb-icccm.so.4 => /usr/lib/libxcb-icccm.so.4 (0x00007f8f0d3c3000)
        libxcb-shm.so.0 => /usr/lib/libxcb-shm.so.0 (0x00007f8f0cdcc000)
        libxcb-render.so.0 => /usr/lib/libxcb-render.so.0 (0x00007f8f0c5d2000)
        libxcb-image.so.0 => /usr/lib/libxcb-image.so.0 (0x00007f8f0c99d000)
        libxcb-xfixes.so.0 => /usr/lib/libxcb-xfixes.so.0 (0x00007f8f0c5c9000)
        libxcb-shape.so.0 => /usr/lib/libxcb-shape.so.0 (0x00007f8f0c5c3000)
        libxcb-sync.so.1 => /usr/lib/libxcb-sync.so.1 (0x00007f8f0c5ba000)
        libxcb-render-util.so.0 => /usr/lib/libxcb-render-util.so.0 (0x00007f8f0c5b4000)
        libxcb-keysyms.so.1 => /usr/lib/libxcb-keysyms.so.1 (0x00007f8f0c5af000)
        libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007f8f0c584000)
        libX11-xcb.so.1 => /usr/lib/libX11-xcb.so.1 (0x00007f8f0b9fb000)
        libfontconfig.so.1 => /usr/lib/libfontconfig.so.1 (0x00007f8f0b9aa000)
        libdbus-1.so.3 => /usr/lib/libdbus-1.so.3 (0x00007f8f0b957000)
        libm.so.6 => /usr/lib/libm.so.6 (0x00007f8f0b839000)
        libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f8f0b5d3000)
        libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f8f0b834000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007f8f0820f000)
        /lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f8f15c91000)
        librt.so.1 => /usr/lib/librt.so.1 (0x00007f8f0b82f000)
        libpcre2-8.so.0 => /usr/lib/libpcre2-8.so.0 (0x00007f8f0ad52000)
        libkrb5.so.3 => /usr/lib/libkrb5.so.3 (0x00007f8f0873a000)
        libk5crypto.so.3 => /usr/lib/libk5crypto.so.3 (0x00007f8f0b5a6000)
        libcom_err.so.2 => /usr/lib/libcom_err.so.2 (0x00007f8f0b5a0000)
        libkrb5support.so.0 => /usr/lib/libkrb5support.so.0 (0x00007f8f0b592000)
        libkeyutils.so.1 => /usr/lib/libkeyutils.so.1 (0x00007f8f0b58b000)
        libresolv.so.2 => /usr/lib/libresolv.so.2 (0x00007f8f0b579000)
        libnss3.so => /usr/lib/libnss3.so (0x00007f8f07ec1000)
        libnssutil3.so => /usr/lib/libnssutil3.so (0x00007f8f0b54c000)
        libnspr4.so => /usr/lib/libnspr4.so (0x00007f8f0ad12000)
        libsmime3.so => /usr/lib/libsmime3.so (0x00007f8f0870e000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f8f07c00000)
        libxcb-util.so.1 => /usr/lib/libxcb-util.so.1 (0x00007f8f0b546000)
        libXau.so.6 => /usr/lib/libXau.so.6 (0x00007f8f0b541000)
        libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007f8f0b539000)
        libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x00007f8f0863e000)
        libexpat.so.1 => /usr/lib/libexpat.so.1 (0x00007f8f07e96000)
        libsystemd.so.0 => /usr/lib/libsystemd.so.0 (0x00007f8f07ada000)
        libplds4.so => /usr/lib/libplds4.so (0x00007f8f0b534000)
        libplc4.so => /usr/lib/libplc4.so (0x00007f8f0b52d000)
        libbz2.so.1.0 => /usr/lib/libbz2.so.1.0 (0x00007f8f0b1ed000)
        libpng16.so.16 => /usr/lib/libpng16.so.16 (0x00007f8f07a9f000)
        libbrotlidec.so.1 => /usr/lib/libbrotlidec.so.1 (0x00007f8f0b1de000)
        libbrotlicommon.so.1 => /usr/lib/libbrotlicommon.so.1 (0x00007f8f07a7c000)
[xtricman@DESKTOP-BFOE35J ~]$ readelf -d /opt/wechat/wechat

Dynamic section at offset 0x82e1bf8 contains 74 entries:
  标记        类型                         名称/值
 0x000000000000001d (RUNPATH)            Library runpath: [${ORIGIN}]
 0x0000000000000001 (NEEDED)             共享库:[libglib-2.0.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libatomic.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libXcomposite.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libXrender.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libXrandr.so.2]
 0x0000000000000001 (NEEDED)             共享库:[libudev.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libX11.so.6]
 0x0000000000000001 (NEEDED)             共享库:[libXext.so.6]
 0x0000000000000001 (NEEDED)             共享库:[libXtst.so.6]
 0x0000000000000001 (NEEDED)             共享库:[libXdamage.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libXfixes.so.3]
 0x0000000000000001 (NEEDED)             共享库:[libgssapi_krb5.so.2]
 0x0000000000000001 (NEEDED)             共享库:[libandromeda.so]
 0x0000000000000001 (NEEDED)             共享库:[libconfService.so]
 0x0000000000000001 (NEEDED)             共享库:[libilink2.so]
 0x0000000000000001 (NEEDED)             共享库:[libilink_network.so]
 0x0000000000000001 (NEEDED)             共享库:[libilink_protobuf.so]
 0x0000000000000001 (NEEDED)             共享库:[libowl.so]
 0x0000000000000001 (NEEDED)             共享库:[libvoipChannel.so]
 0x0000000000000001 (NEEDED)             共享库:[libvoipCodec.so]
 0x0000000000000001 (NEEDED)             共享库:[libvoipComm.so]
 0x0000000000000001 (NEEDED)             共享库:[libmmmojo.so]
 0x0000000000000001 (NEEDED)             共享库:[libz.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libdl.so.2]
 0x0000000000000001 (NEEDED)             共享库:[libxkbcommon.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxkbcommon-x11.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-glx.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-xkb.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-randr.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-icccm.so.4]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-shm.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-render.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-image.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-xfixes.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-shape.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-sync.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-render-util.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libxcb-keysyms.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libxcb.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libX11-xcb.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libfontconfig.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libdbus-1.so.3]
 0x0000000000000001 (NEEDED)             共享库:[libm.so.6]
 0x0000000000000001 (NEEDED)             共享库:[libgcc_s.so.1]
 0x0000000000000001 (NEEDED)             共享库:[libpthread.so.0]
 0x0000000000000001 (NEEDED)             共享库:[libc.so.6]
 0x0000000000000001 (NEEDED)             共享库:[ld-linux-x86-64.so.2]
 0x0000000000000001 (NEEDED)             共享库:[librt.so.1]
 0x000000006ffffffb (FLAGS_1)            标志: PIE
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000007 (RELA)               0xc8f8
 0x0000000000000008 (RELASZ)             10240848 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffff9 (RELACOUNT)          426634
 0x0000000000000017 (JMPREL)             0x9d0c48
 0x0000000000000002 (PLTRELSZ)           25296 (bytes)
 0x0000000000000003 (PLTGOT)             0x84614c0
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000006 (SYMTAB)             0x340
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000005 (STRTAB)             0x7500
 0x000000000000000a (STRSZ)              21492 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x74d8
 0x0000000000000019 (INIT_ARRAY)         0x7fa6618
 0x000000000000001b (INIT_ARRAYSZ)       7568 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x7fa6600
 0x000000000000001c (FINI_ARRAYSZ)       24 (bytes)
 0x000000000000000c (INIT)               0x7fa103c
 0x000000000000000d (FINI)               0x7fa1058
 0x000000006ffffff0 (VERSYM)             0x69b8
 0x000000006ffffffe (VERNEED)            0x7244
 0x000000006fffffff (VERNEEDNUM)         12
 0x0000000000000000 (NULL)               0x0

于是我怀疑是不是动态链接器在ns内运行时会有一些对DT_RUNPATH的奇怪处理,尝试运行了unshare -c -m -C /opt/wechat/wechat来模拟ns中运行wechat,发现并不会报错,所以问题应该还是单纯的我少bind了一些东西。

要不你strace或者perf trace看看?

说实话俩工具我都不是很会用呢。strace bwrap只会看见bwrap的 syscall,至于perf trace 嘛……

[xtricman@DESKTOP-BFOE35J ~]$ perf trace /usr/bin/bwrap \
--unshare-cgroup \
--symlink usr/lib /lib \
--symlink usr/lib /lib64 \
--ro-bind /usr/lib /usr/lib \
--ro-bind /usr/bin /usr/bin \
--bind /run /run \
--ro-bind /etc /etc \
--ro-bind /usr/share /usr/share \
--ro-bind /run /run \
--ro-bind /opt /opt \
/opt/wechat/wechat
libbpf: Failed to bump RLIMIT_MEMLOCK (err = -EPERM), you might need to do it explicitly!
libbpf: Error in bpf_object__probe_loading(): -EPERM. Couldn't load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y) and/or that RLIMIT_MEMLOCK is set to big enough value.
libbpf: failed to load BPF skeleton 'augmented_raw_syscalls_bpf': -EPERM
Error:  File /sys/kernel/tracing//events/raw_syscalls/sys_(enter|exit) not found.
Hint:   Perhaps this kernel misses some CONFIG_ setting to enable this feature?.

似乎普通用户不行?但是sudo会改变bwrap程序和ld-linux.so的某些行为吧。今天好晚了,我明天晚上再看看好了。

-f来跟踪子进程。

似乎看见微信进程在尝试打开/usr/lib/glibc-hwcaps/x86-64-v3/libandromeda.so,然后又尝试了/usr/lib/glibc-hwcaps/x86-64-v2/libandromeda.so和/usr/lib/libandromeda.so,因为不存在所以全部失败了,然后就报错退出了。
但是为什么会去打开这些地方的libandromeda.so呢……这个DT_RUNPATH的处理感觉还是有点迷惑。我不是很懂,总觉得根据readelf -d的输出来看它应该从自身目录找东西的……这下真的要明天晚上再看了。
或许我应该往/usr/lib上overlay一些so……

没有尝试$ORIGIN吗?

要不然你给我贴个文档链接描述一下这个DT_RUNPATH和这个什么$ORIGIN的行为?

好像是加入--proc /proc就不会报这个错了。现在命令行长这样:

/usr/bin/bwrap \
--unshare-cgroup \
--symlink usr/lib /lib \
--symlink usr/lib /lib64 \
--ro-bind /usr/lib /usr/lib \
--ro-bind /usr/bin /usr/bin \
--ro-bind /etc /etc \
--ro-bind /usr/share /usr/share \
--ro-bind /opt/wechat /opt/wechat \
--ro-bind /usr/lib/flatpak-xdg-utils/xdg-open /usr/bin/xdg-open \
--dev /dev \
--proc /proc \
--tmpfs /tmpfs \
--dev-bind /dev/dri /dev/dri \
--ro-bind /sys/dev/char /sys/dev/char \
--ro-bind /sys/devices /sys/devices \
--bind /run/user/60200 /run/user/60200 \
--ro-bind /run/user/60200/wayland-0 /run/user/60200/wayland-0 \
--ro-bind /run/user/60200/pipewire-0 /run/user/60200/pipewire-0 \
--ro-bind /run/user/60200/pulse /run/user/60200/pulse \
--bind /run/user/60200/doc /run/user/60200/doc \
--bind /home/xtricman/.local/share/WeChat_Data /home/xtricman/ \
--bind /home/xtricman/.local/share/WeChat_Data/bus /run/user/60200/bus \
--ro-bind /home/xtricman/.local/share/WeChat_Data/.flatpak-info /.flatpak-info \
/opt/wechat/wechat

开始报不一样的错误了,

[0217/230008.555075:ERROR:directory_reader_posix.cc(42)] opendir /home/xtricman/.xwechat/crashinfo/attachments/5a33e1ad-2cd4-4e59-a992-66bd75040a4b: No such file or directory (2)
[0217/230008.564773:ERROR:http_transport_socket.cc(302)] getaddrinfo: Resource temporarily unavailable (11)
[0217/230008.612937:ERROR:directory_reader_posix.cc(42)] opendir /home/xtricman/.xwechat/crashinfo/attachments/5a33e1ad-2cd4-4e59-a992-66bd75040a4b: No such file or directory (2)
[0217/230008.624455:ERROR:http_transport_socket.cc(302)] getaddrinfo: Resource temporarily unavailable (11)
[0217/230008.744783:ERROR:elf_dynamic_array_reader.h(64)] tag not found
[0217/230008.777326:ERROR:http_transport_socket.cc(302)] getaddrinfo: Resource temporarily unavailable (11)
[0217/230008.777903:ERROR:directory_reader_posix.cc(42)] opendir /home/xtricman/.xwechat/crashinfo/attachments/ac6744e4-b248-4af6-b76e-14dc1a4b3950: No such file or directory (2)
[0217/230008.789260:ERROR:http_transport_socket.cc(302)] getaddrinfo: Resource temporarily unavailable (11)
[0217/230008.790488:ERROR:directory_reader_posix.cc(42)] opendir /home/xtricman/.xwechat/crashinfo/attachments/5a33e1ad-2cd4-4e59-a992-66bd75040a4b: No such file or directory (2)

似乎是微信找不到某些文件,但是我检查了我的/home/xtricman/.local/share/WeChat_Data/.xwechat/crashinfo/,我确定这个.wechat目录是微信创建的因为运行之前它都不存在,但是不知道为什么attachments里面不会生成任何文件。

顺便一提,把 XDG_RUNTIME_DIR bind 进沙盒是不安全的。另外且不提 Wayland 合成器的特权协议,pipewire 应该也是不能直接 bind 进沙盒的,而 pipewire-pulse 在不存在 .flatpak-info 的情况下我也不确定是否安全

你之前居然把这个漏掉了……

你是不是在用systemd-resolved、/etc/resolv.conf是软链接?

这个/proc跟ld-linux.so有什么关系吗?

我在用systemd-resolved,可能是libnss_resolve.so.2在跟systemd-networkd通讯不上?

其实有.flatpak-info……完整的程序是个Python脚本,还在慢慢改。我没贴。

wayland的问题大概得上way-secure之类的才能用上security context了。这个暂时先不做了。

至于pulseaudio或pipewire我真的就完全没看过协议了,把它们的socket直接bind进沙盒有什么不安全的地方?

$ORIGIN要用的。

那肯定通讯不上啊,你又没把system dbus弄进去。

反正 pipewire 文档提及也有一个 security context,但是只有 API reference 没有说明其行为的文档,我也没深入了解过。另外 pipewire 有个漏洞,任何客户端都可以阻塞整个 pipewire 的音频播放:https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/4463

pipewire-pulse 听说是会对 flatpak 客户端做一些特殊处理,不过我也没看过源码不是很了解。

(最主要是我甚至不了解 pulseaudio 和 pipewire 协议通过它们的 socket 通过给客户端哪些功能,要搞清楚它们是否适合沙箱首先得搞清楚这个,然后才是在沙箱里允许哪些、限制哪些功能

说的好有道理,可是bwrap不支持hidepid挂载/proc吧,我记得我看bwrap源码是没有suid-root的话会直接bind host的proc(不知道是不是内核限制)。
要不然我试试--bind /proc/self /proc/self ?

目前是这样子的脚本(用https://forum.archlinuxcn.org/t/topic/15039改的),还有俩问题

  • nss-resolve文档说Communication between nss-resolve and systemd-resolved.service takes place via the /run/systemd/resolve/io.systemd.Resolve AF_UNIX socket.然而/run/systemd是不够的,会产生Authorization required, but no authorization protocol specified报错,换成/run就可以了,这个varlink服务还需要认证么?
  • 另外就是xdg-dbus-proxy好像少放行了什么东西,微信无法调用使用“在文件管理器中打开”。
#!/usr/bin/python
import os
import subprocess
import time
from pathlib import Path
import pdb

# -----------------------------
# 🧩 基本配置
# -----------------------------
APP_NAME = "com.qq.wechat"
XDG_RUNTIME_DIR = Path(os.environ.get("XDG_RUNTIME_DIR", f"/run/user/{os.getuid()}"))
HOME = Path(os.environ.get("HOME", f"/home/{os.getlogin()}"))
APP_FOLDER = HOME/".local"/"share"/"WeChat_Data"
WECHAT_BIN = "/opt/wechat/wechat"

# -----------------------------
# 🧠 环境变量初始化
# -----------------------------
if "DBUS_SESSION_BUS_ADDRESS" not in os.environ:
    os.environ["DBUS_SESSION_BUS_ADDRESS"] = f"unix:path={XDG_RUNTIME_DIR}/bus"

# -----------------------------
# 🧱 启动 xdg-dbus-proxy(使用唯一的 APP_FOLDER/bus)
# -----------------------------
def set_up_dbus_proxy():
    proxy_log = APP_FOLDER / "xdg-dbus-proxy.log"
    args = [
        "/usr/bin/bwrap",
        "--new-session",
        "--die-with-parent",
        "--symlink", "usr/lib", "/lib",
        "--symlink", "usr/lib", "/lib64",
        "--ro-bind", "/usr/lib", "/usr/lib",
        "--ro-bind", "/usr/bin", "/usr/bin",
        "--bind", str(XDG_RUNTIME_DIR), str(XDG_RUNTIME_DIR),
        "--bind", str(APP_FOLDER), str(APP_FOLDER),
        "--ro-bind", str(flatpak_info), "/.flatpak-info",
        "/usr/bin/xdg-dbus-proxy",
        os.environ["DBUS_SESSION_BUS_ADDRESS"],
        f"{APP_FOLDER}/bus",  # 修改:使用唯一的 bus 路径
        "--log",
        "--filter",
        "--talk=org.kde.StatusNotifierWatcher",
        "--talk=org.freedesktop.portal.*",
    ]
    with open(proxy_log, "wb") as log:
        proc = subprocess.Popen(args, stdout=log, stderr=log)
    return proc

def run_app():
    args = [
        "/usr/bin/bwrap",
        "--unshare-cgroup",
        "--die-with-parent",
        "--ro-bind", str(flatpak_info), "/.flatpak-info",
        "--symlink", "usr/lib", "/lib",
        "--symlink", "usr/lib", "/lib64",
        "--ro-bind", "/usr/lib", "/usr/lib",
        "--ro-bind", "/usr/bin", "/usr/bin",
        "--ro-bind", "/etc", "/etc",
        "--ro-bind", "/usr/share", "/usr/share",
        "--ro-bind", "/opt/wechat", "/opt/wechat",
        "--ro-bind", "/usr/lib/flatpak-xdg-utils/xdg-open", "/usr/bin/xdg-open",
        "--dev", "/dev",
        "--bind", "/proc","/proc",
        "--tmpfs", "/tmp",
        "--dev-bind", "/dev/dri", "/dev/dri",
        "--ro-bind", "/sys/dev/char", "/sys/dev/char",
        "--ro-bind", "/sys/devices", "/sys/devices",
        "--bind", "/run/systemd", "/run/systemd",
        "--bind", str(XDG_RUNTIME_DIR / "wayland-0"), str(XDG_RUNTIME_DIR / "wayland-0"),
        "--bind", str(XDG_RUNTIME_DIR / "pipewire-0"), str(XDG_RUNTIME_DIR / "pipewire-0"),
        "--bind", str(XDG_RUNTIME_DIR / "pulse"), str(XDG_RUNTIME_DIR / "pulse"),
        "--bind", str(XDG_RUNTIME_DIR / "doc"), str(XDG_RUNTIME_DIR / "doc"),
        "--bind", str(APP_FOLDER), str(HOME),
        "--bind", f"{APP_FOLDER}/bus", f"{XDG_RUNTIME_DIR}/bus", 
        WECHAT_BIN,
    ]
    print(args)
    proc = subprocess.Popen(args)
    return proc

# -----------------------------
# 🪄 主流程
# -----------------------------
if __name__ == "__main__":
    print(f"[+] Setting up sandbox for {APP_NAME} ...")
    APP_FOLDER.mkdir(0o777, True, True)
    flatpak_info = APP_FOLDER / ".flatpak-info"
    flatpak_info.write_text(
    "[Application]\n"
    f"name={APP_NAME}\n",
    encoding="utf-8"
    )
    proxy_proc = set_up_dbus_proxy()
    time.sleep(0.2)  # 给 dbus proxy 启动时间
    app_proc = run_app()
    print(f"[+] WeChat started in sandbox (PID {app_proc.pid})")
    app_proc.wait()
    proxy_proc.wait()

--proc 并不是 bind mount 啊,它是挂载当前 pidns 的 procfs。哦对,你没有 unshare-pid,这是必要的,不然沙盒进程可以用 signal 逃逸。我是除了 unshare-net 之外全都 unshare 了的

我是打算不unshare pidns尝试用hidepid=4重新挂载procfs的,systemd的ProtectProc似乎能在userns下提供这个功能的,但bwrap没有。况且这个问题是我眼见能简单解决的。

我眼下更关注的问题是我楼上说的那个nss-resolve的问题啦,难道这个又要去看systemd源码了吗……

hidepid 并不是合理的安全边界,这只是限制了 procfs 的访问,哪怕根本不挂载 procfs 进程还是能直接通过 syscall 与别的 pid 交互,比如发送 signal。

varlink 通不通其实没那么重要,只要沙盒内能访问 127.0.0.53:53 的本地 dns 服务就足够用了