banner
约 2,100 字
7 分钟

Flatpak 微信获得了 Home 权限,却无法访问下载目录

摘要

我在使用 Flatpak 版微信时,虽拥有 Home 目录读写权限,却无法访问下载目录。经排查发现,具体路径在沙盒中被标记为“hidden”,这是由于用户级或系统级 override 导致的。解决方案是使用 `flatpak override` 命令明确恢复下载目录权限并重启应用。此次排查表明,不能仅依赖大范围权限判断,需检查 Flatpak 对具体路径的最终访问级别。

最近在 Fedora 上使用 Flatpak 版本微信时遇到了一个反直觉的问题:

我已经给微信授予了整个 Home 目录的读写权限,微信也确实能够读写家目录中的其他位置,但偏偏无法正常访问系统的“下载”目录。

从表面上看,这似乎不合理:

纯文本
/home/ulinoyaped
├── 文档        微信可以访问
├── 图片        微信可以访问
├── 其他目录    微信可以访问
└── 下载        微信无法访问

如果微信已经获得了 home 权限,那么位于家目录中的 ~/下载 理论上也应该包含在授权范围内。问题究竟出在哪里?

本文记录这次问题的完整排查过程,也顺便说明几个容易混淆的 Flatpak 权限概念。

问题现象

微信的 Flatpak 应用 ID 为:

bash
com.tencent.WeChat

首先查看应用当前的实际权限:

bash
flatpak info --show-permissions com.tencent.WeChat

输出如下:

纯文本
[Context]
shared=network;ipc;
sockets=x11;pulseaudio;
devices=all;
filesystems=home;xdg-config/fcitx5:ro;
persistent=.xwechat;xwechat_files;

[Session Bus Policy]
org.kde.StatusNotifierWatcher=talk
org.freedesktop.Notifications=talk
org.kde.*=own
org.freedesktop.FileManager1=talk

[Environment]
QT_IM_MODULE=fcitx
XMODIFIERS=@im=fcitx
QT_QPA_PLATFORM=xcb
GTK_IM_MODULE=fcitx
QT_AUTO_SCREEN_SCALE_FACTOR=1

最关键的是这一行:

纯文本
filesystems=home;xdg-config/fcitx5:ro;

其中:

纯文本
home

表示应用可以访问用户的整个家目录。

它后面没有 :ro,所以默认是读写权限,而不是只读权限。

另一项:

纯文本
xdg-config/fcitx5:ro

只表示应用能够以只读方式访问 Fcitx 5 的配置目录,与下载目录无关。

因此,仅从这份权限列表来看,微信应该可以读写:

纯文本
/home/ulinoyaped/下载

最初的错误假设

看到“其他 Home 目录可写,下载目录不可写”这种现象时,一个很自然的猜测是:微信可能获得了整个 Home 目录权限,但下载目录又被单独设置成了只读,例如:

纯文本
home
xdg-download:ro

这会形成一种“父目录允许读写、子目录单独只读”的效果。

不过实际权限输出中并没有:

纯文本
xdg-download:ro

所以这个猜测与现有证据不符,必须放弃。

这也是排查 Flatpak 问题时很重要的一点:不要只根据 Flatseal 界面或应用表现推断权限,应当查看 Flatpak 最终计算出的权限。

确认系统下载目录的真实位置

Linux 桌面环境中的“下载目录”不一定固定是:

纯文本
~/Downloads

中文环境下通常是:

纯文本
~/下载

也可能因为用户修改过 XDG 用户目录配置,而指向其他路径。

使用下面的命令查询:

bash
download="$(xdg-user-dir DOWNLOAD)"

printf 'XDG 下载目录:%s\n' "$download"
printf '解析后的真实路径:'
readlink -f -- "$download"

ls -ld -- "$download"
namei -l -- "$download"

实际输出为:

纯文本
XDG 下载目录:/home/ulinoyaped/下载
/home/ulinoyaped/下载
drwxr-xr-x. 3 ulinoyaped ulinoyaped 4096  6月11日 10:28 /home/ulinoyaped/下载
f: /home/ulinoyaped/下载
dr-xr-xr-x root       root       /
drwxr-xr-x root       root       home
drwx------ ulinoyaped ulinoyaped ulinoyaped
drwxr-xr-x ulinoyaped ulinoyaped 下载

这段结果排除了几个常见原因。

首先,下载目录的真实路径就是:

纯文本
/home/ulinoyaped/下载

它不是指向其他磁盘或 /mnt 目录的软链接。

其次,目录所有者是当前用户:

纯文本
ulinoyaped:ulinoyaped

权限为:

纯文本
drwxr-xr-x

对于目录所有者来说,前三位是:

纯文本
rwx

也就是拥有读取目录、进入目录和创建或删除目录项的权限。

路径上的每一级目录也都允许当前用户正常通过。因此,宿主系统的传统 Unix 文件权限没有明显问题。

关键证据:查询 Flatpak 对具体路径的判断

flatpak info --show-permissions 适合查看应用的整体权限,但它未必能直观回答某一个具体路径最终是否可访问。

Flatpak 还提供了一个非常有用的检查方式:

bash
flatpak info --file-access=路径 应用ID

针对下载目录执行:

bash
download="$(xdg-user-dir DOWNLOAD)"

flatpak info \
  --file-access="$download" \
  com.tencent.WeChat

得到的结果不是预期中的:

纯文本
read-write

而是:

纯文本
hidden

这就是整个排查过程中的决定性证据。

hidden 表示这个路径在应用的沙盒视图中被隐藏。对微信来说,该目录并不是简单的“没有写权限”,而是根本没有作为正常宿主目录暴露到沙盒中。

这也解释了为什么修改普通 Linux 文件权限没有意义:问题并不发生在 ext4、Btrfs 或 Unix 权限层,而是发生在 Flatpak 建立沙盒文件系统视图的阶段。

为什么 home 存在,子目录仍可能显示为 hidden

Flatpak 的权限并不一定只有应用包自身声明的那一层。

一个应用运行时的最终权限,可能同时受到以下来源影响:

纯文本
应用自身的元数据
系统级全局 override
系统级应用 override
用户级全局 override
用户级应用 override
临时传给 flatpak run 的参数

因此,即使基础权限中存在:

纯文本
home

更具体的规则仍可能把某个目录从沙盒中排除。

概念上相当于:

纯文本
/home/ulinoyaped             允许访问
└── /home/ulinoyaped/下载    单独隐藏

更具体的路径规则会影响这个子目录最终的可见性。

需要注意的是,单凭一次 hidden 输出,还不能武断地断定隐藏规则究竟来自哪一个配置文件。它可能来自 Flatseal 生成的用户级覆盖,也可能来自系统级或全局覆盖。

正确做法是继续查看各层 override。

检查 Flatpak override

先查看当前用户针对微信设置的覆盖:

bash
flatpak override --user --show com.tencent.WeChat

查看系统级针对微信设置的覆盖:

bash
flatpak override --system --show com.tencent.WeChat

再检查用户级全局覆盖:

bash
flatpak override --user --show

以及系统级全局覆盖:

bash
flatpak override --system --show

重点寻找与下载目录有关的排除项,例如:

ini
[Context]
filesystems=!xdg-download;

或者:

ini
[Context]
filesystems=!~/下载;

感叹号表示撤销或拒绝相应资源的访问权限。

如果曾经在 Flatseal 中关闭过下载目录权限,就可能产生类似的用户级 override。Flatseal 本质上是在帮助用户编辑 Flatpak override,而不是直接修改应用包本身。

直接为微信恢复下载目录读写权限

不必修改整个 Home 权限,只需要针对微信明确授予 XDG 下载目录即可:

bash
flatpak override --user \
  --filesystem=xdg-download \
  com.tencent.WeChat

这里没有添加 :ro,因此默认授予读写权限。

使用 xdg-download 比直接写:

纯文本
/home/ulinoyaped/下载

更规范,因为 Flatpak 会根据当前用户的 XDG 配置解析真正的下载目录。以后即使把下载目录从 ~/下载 改到其他位置,这条规则仍然具有明确的语义。

修改权限后,必须彻底结束已经运行的微信实例:

bash
flatpak kill com.tencent.WeChat

然后重新启动:

bash
flatpak run com.tencent.WeChat

已经运行的沙盒不会自动重新构建挂载和权限,因此只关闭窗口并不一定足够。

验证修复结果

再次查询具体路径:

bash
flatpak info \
  --file-access="$(xdg-user-dir DOWNLOAD)" \
  com.tencent.WeChat

预期输出应为:

纯文本
read-write

还可以直接用微信的 Flatpak 沙盒启动一个 Shell,并在下载目录创建测试文件:

bash
flatpak run --command=sh com.tencent.WeChat -c '
download="$(xdg-user-dir DOWNLOAD)"

touch "$download/.wechat-flatpak-test" &&
rm "$download/.wechat-flatpak-test" &&
echo "沙盒内可以正常读写下载目录"
'

如果输出:

纯文本
沙盒内可以正常读写下载目录

就说明 Flatpak 文件系统权限已经恢复。

此时如果微信界面仍无法保存文件,问题就已经不再属于 Flatpak 文件系统权限,而更可能是微信自身保存路径、文件选择器或应用状态的问题。

结论

本次问题并不是 Linux 下载目录本身不可写,也不是下载目录指向了 Home 之外的磁盘。

已经确认:

纯文本
下载目录位于 /home/ulinoyaped/下载
目录不是软链接
目录所有者和 Unix 权限正常
微信拥有 home 读写权限

真正的关键证据是:

bash
flatpak info \
  --file-access=/home/ulinoyaped/下载 \
  com.tencent.WeChat

返回:

纯文本
hidden

这说明下载目录在微信的 Flatpak 沙盒中被单独隐藏。处理方式是检查用户级、系统级和全局 override,并为微信明确恢复下载目录权限:

bash
flatpak override --user \
  --filesystem=xdg-download \
  com.tencent.WeChat

flatpak kill com.tencent.WeChat
flatpak run com.tencent.WeChat

最后通过:

bash
flatpak info \
  --file-access="$(xdg-user-dir DOWNLOAD)" \
  com.tencent.WeChat

确认结果已经变为:

纯文本
read-write

这次排查最值得记住的不是某一条修复命令,而是下面这条原则:

纯文本
不要只看应用拥有哪一类大范围权限,
还要查询 Flatpak 对具体路径计算出的最终访问级别。

END