Devtools chroot 被用戶 run 目錄污染事件
概況
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