Devtools chroot 被用户 run 目录污染事件

来自Arch Linux 中文社区 维护者 Wiki
跳转到导航 跳转到搜索

概况

2019年12月1日凌晨一点,lilydjwg 收到多封 lilac 的报错。错误信息如下:

==> ERROR: '/var/lib/archbuild/extra-x86_64/root' does not appear to be an Arch chroot.
==> ERROR: Aborting...

随后发现几乎所有 lilac 包都遇到此错误。调查发现 /var/lib/archbuild/extra-x86_64/root 下有一个已挂载的系统 /run 目录,里边包含一些用户 run 目录的挂载。

事故调查

根据目录中残留的文件确定时间戳:

1712 (archlinuxcn-build-e5) /var/lib/archbuild/extra-x86_64
### stat root
  文件:root
  大小:60              块:0          IO 块:4096   目录
设备:2dh/45d   Inode:66952       硬链接:3
权限:(0755/drwxr-xr-x)  Uid:(    0/    root)   Gid:(    0/    root)
最近访问:2019-11-30 23:43:32.647435418 +0800
最近更改:2019-11-30 23:43:11.560712233 +0800
最近改动:2019-11-30 23:43:11.560712233 +0800
创建时间:-
1713 (archlinuxcn-build-e5) /var/lib/archbuild/extra-x86_64
### stat root.lock
  文件:root.lock
  大小:0               块:0          IO 块:4096   普通空文件
设备:2dh/45d   Inode:70381120    硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
最近访问:2019-11-30 23:43:36.414112131 +0800
最近更改:2019-12-01 01:47:50.312800053 +0800
最近改动:2019-12-01 01:47:50.312800053 +0800
创建时间:-

然后分析 journalctl 日志。

事件线

  • Nov 25 20:46:27 system boot
  • Nov 25 20:50:41 megumifox extra-x86_64-build
  • Nov 25 20:51:04 megumifox initilizing root chroot
  • Nov 25 20:51:04 a-wing run acquire
  • Nov 25 20:51:09 a-wing run release
  • Nov 25 20:51:09 root chroot release, axionl sees umount of run, others see umount of a-wing's run
  • Nov 25 22:22:34 yan12125 run release, root/run already polluted
  • Nov 30 23:42:32 dctxmei login
  • Nov 30 23:43:11 dctxmei extra-x86_64-build -c
  • Nov 30 23:43:32 dctxmei extra-x86_64-build -c

run acquire 表示用户的 run 目录被挂载,run release 表示被卸载。

在开机后不久,由于 /var/lib/archbuild 目录为空,devtools 会开始建立新的 root chroot。这时刚好 a-wing 登录,导致 run 目录的挂载事件被扩散到 chroot 内。数天后,dctxmei 使用 -c 参数重建 root chroot 时失败,问题显现。

解决方案

临时

umount -l 有问题的 run 目录,然后 rm -r --one-file-system 删除整个 extra-x86_64。

长期

修改 devtools-archlinuxcn 中的 mkarchroot 脚本,在调用 pacstrap 时使用 unshare 以避免系统的挂载扩散进去。

diff -Naur a/usr/bin/mkarchroot b/usr/bin/mkarchroot
--- a/usr/bin/mkarchroot        2019-11-19 16:26:19.000000000 +0800
+++ b/usr/bin/mkarchroot        2019-12-01 18:04:51.762383615 +0800
@@ -332,7 +332,7 @@
        cp "$file" "$working_dir$file"
 done
 
-pacstrap -Mcd ${pac_conf:+-C "$pac_conf"} "$working_dir" \
+unshare -m pacstrap -Mcd ${pac_conf:+-C "$pac_conf"} "$working_dir" \
        "${cache_dirs[@]/#/--cachedir=}" "$@" || die 'Failed to install all packages'
 
 printf '%s.UTF-8 UTF-8\n' en_US de_DE > "$working_dir/etc/locale.gen"

类似事故

前不久发现过一起类似的事故,由于当时 build-cleaner 清理脚本未做跨文件系统的检查,直接导致 system D-Bus 的 socket 文件被删除,进而计划重启。

  • Nov 18 21:30:10 felix run acquire
  • Nov 18 22:02:32 felix extra-x86_64-build start
  • Nov 18 22:06:20 felix extra-x86_64-build end
  • Nov 18 22:14:23 felixonmars2 run acquire
  • Nov 18 22:22:06 felix chroot release without /run
  • Nov 18 22:27:16 yan12125 run acquire
  • Nov 18 22:31:45 yan12125 run release, felixonmars2/run & felix/run already polluted
  • Nov 18 22:57   felixonmars2 chroot known broken with tmp
  • Nov 19 01:41:33 yan12125 run acquire
  • Nov 19 02:48:52 yan12125 run release
  • Nov 19 09:42:57 felixonmars2 chroot release
  • Nov 19 09:43:07 felixonmars2 logout
  • Nov 19 09:43:07 felix logout
  • Nov 19 09:43:07 felix run release
  • Nov 19 09:43:07 felixonmars2 run release
  • Nov 19 09:57    felixonmars2 chroot recovered
  • Nov 19 09:57    felix chroot known broken with /run 1053 (felixonmars3)
  • Nov 20 13:29:10 felix still has processes running
  • Nov 25 20:44:07 felixonmars3 logout

事故一开始是 felixonmars2 的 chroot 中包含已挂载的 tmp 目录从而清理失败。到第二天上午的时候,登出导致该 chroot 下的诸多文件系统被卸载,此 chroot 恢复正常。然而 felix chroot 依旧有问题,直接后来手工卸载。

几个疑点:

  • felixonmars2 chroot 为什么隔了数小时才开始卸载?此时锁文件为什么没有被上锁?是使用该 chroot 的进程有泄漏吗?
  • felix chroot 的 run 目录为什么会被挂载在外面的 mount ns?除了 root chroot 之外,用户的 chroot 应当只会通过 arch-nspawn 使用 systemd-nspawn,其挂载是私有的,也没有看到有 bind mount /run 的地方。

外部链接

  • devtools 上游的 bug 报告:FS#64698