SnapパッケージをNFS上で起動する場合はAppArmorに注意

UbuntuなどのLinuxディストリビューションで、比較的新しいソフトウェアをインストールするためにSnapパッケージを利用することがあるかと思います。このSnapパッケージについてNFSマウントしたディレクトリ上では起動しないという不具合に遭遇したので、原因と暫定対処策をメモしておきます。Ubuntu 22.04 LTSで確認しています。

例としてKotlinのSnapパッケージをインストールしてみます。

~$ sudo snap install kotlin
…

~$ kotlin -version
Kotlin version 1.7.21-release-272 (JRE 17.0.5+8-Ubuntu-2ubuntu122.04)

~$ cd /nfs
/nfs$ kotlin -version
cannot open path of the current working directory: Permission denied

このようにNFS上ではKotlinが起動しません。原因はAppArmorがプロセスをブロックしてしまっているためで、syslogでその様子を確認できます。

Jan 24 22:08:09 ubuntu2204-01 systemd[1099]: Started snap.kotlin.kotlin.2c2e7cf1-5e19-43f0-853f-0f1eee666559.scope.
Jan 24 22:08:09 ubuntu2204-01 kernel: [   76.634145] nfs: RPC call returned error 13
Jan 24 22:08:09 ubuntu2204-01 kernel: [   76.634166] kauditd_printk_skb: 31 callbacks suppressed
Jan 24 22:08:09 ubuntu2204-01 kernel: [   76.634168] audit: type=1400 audit(1674565689.275:43): apparmor="DENIED" operation="sendmsg" profile="/snap/snapd/17950/usr/lib/snapd/snap-confine" pid=1336 comm="snap-confine" laddr=192.168.1.148 lport=800 faddr=192.168.1.2 fport=2049 family="inet" sock_type="stream" protocol=6 requested_mask="send" denied_mask="send"

以下のような仕組みになっているようです。

  • Snapパッケージはsnap-confineというコマンド経由で起動される
  • snap-confineはAppArmorによってネットワーク処理が禁止されている
  • NFS上ではファイルアクセスがネットワーク処理だと解釈されてブロックされてしまう

関連リンクです。

  • AppArmorがNFSアクセスをネットワーク処理として取り扱うことが間違いではないか?という報告。2023年1月時点であまり進展はありません。
  • Snap側でNFS上でも起動するように対処するべきではないか?という議論。ホームディレクトリ自体をNFSマウントしている環境で困っている人が多いようです。


暫定対処策です。AppArmorを丸ごと無効化してしまいたくなるところですがそれでは影響が大きすぎるので、さしあたりsnap-confineにネットワーク処理を許可することにします。

syslogを見るとAppArmorに /snap/snapd/17950/usr/lib/snapd/snap-confine というプロファイルが登録されていることが分かります。このプロファイルの設定は /var/lib/snapd/apparmor/profiles に格納されています。ちなみに17950というのはsnapdの内部的なリビジョン番号を表しています。

設定ファイルの末尾にnetwork,を追加します。カンマを付け忘れると動きませんので注意してください。

~$ sudo vim /var/lib/snapd/apparmor/profiles/snap-confine.snapd.17950
…
    deny /etc/nsswitch.conf r,
    deny /etc/passwd r,

    network,
}

snapd.apparmorサービスを再起動します。

~$ sudo systemctl restart snapd.apparmor

これでNFS上でもSnapパッケージが起動するようになりました。

~$ cd /nfs
/nfs$ kotlin -version
Kotlin version 1.7.21-release-272 (JRE 17.0.5+8-Ubuntu-2ubuntu122.04)

注意点として、Snapパッケージを追加、削除するとプロファイルが上書きされて元に戻ってしまうため、プロファイルを再度編集することになる点があります。暫定対処策なので、これくらいは仕方ないかなと考えています。