[AppArmor] Ubuntu 23.10以降では非特権ユーザーのuser namespace作成に制限がある
Ubuntu 22.04 から 24.04 にアップグレードする機会があったのですが、その際にuser namespace周りの問題が発生したので調査しました。
参考文献
- Jacob, 2024, 「‘unshare -r’ on ubuntu 24.04, 23.10」, jacob's Web, 2026年3月23日, https://nitrojacob.wordpress.com/2024/08/14/unshare-r-on-ubuntu-24-04-23-10/
- AppArmor, 2026, 「unprivileged_userns_restriction」, apparmor, 2026年3月24日, https://gitlab.com/apparmor/apparmor/-/wikis/unprivileged_userns_restriction
user namespaceって何
詳細についてはman pageを参照していただくとして、簡単に説明します。user namespaceはLinuxの機能の1つで、UIDおよびGIDの名前空間を分離する機能を持ちます。AppArmorなどのセキュリティモジュールで制限されていない限り、非特権ユーザーでも次のコマンドでuser namespaceを作成することができます:
id # uid=1000(user) gid=1000(user) groups=1000(user) unshare --map-user=10000 --map-group=10000 # user namespace を作成する id # uid=10000 gid=10000 groups=10000,65534(nogroup)
unshare の実行前後でUIDとGIDが変わっています。これは unshare コマンドを実行したことにより、新しい user namespace が作成され、その中でシェルが UID=10000, GID=10000 で起動したためです。
同様にして、新しい user namespace で UID=0 を獲得することもできます:
id # uid=1000(user) gid=1000(user) groups=1000(user) unshare -Ur # user namespace を作成し、その中でrootユーザーになる id # uid=0(root) gid=0(root) groups=0(root),65534(nogroup)
このnamespace内でのrootユーザーは、本来のrootユーザー (global rootと言います) ではないため、次のような操作は失敗します:
unshare -Ur # 新しいuser namespaceでrootユーザーになる touch /root/test # エラー
しかし、mountを含む一部の操作は可能です (ただし mount namespaceも作成の必要あり):
unshare -Urm # 新しいuser namespaceでrootユーザーになり、mount namespaceも作成する mkdir test mount -t tmpfs tmpfs test
非特権ユーザーによるuser namespace作成の応用
非特権ユーザーによるuser namespaceの作成は、rootlessコンテナの作成に応用されていました。コンテナの作成時には通常、様々なファイルシステムのマウントを行いますが、user namespace (とmount namespace) を作ることで、global rootユーザーの協力なしにファイルシステムをマウントすることができます。
Ubuntu 23.10以降での変更点
Ubuntu 23.10以降ではAppArmor周りの構成が変更され、デフォルトで非特権ユーザーがuser namespaceを作成する際に制限がかかるようになっています。これは、非特権ユーザーが従来のrootユーザーに準じる操作をできることにより、Linuxカーネルの攻撃経路が増えてしまっていたからのようです。具体的には次の制限のいずれかがかかるようです:
- 非特権ユーザーはuser namespaceを作成できない
- 非特権ユーザーはuser namespaceを作成できるが、その中でできる作業に制限がある
Two types of restrictions
AppArmor is capable of two styles of restrictions, denying the unprivileged unconfined from creating new user namespaces, and allow unprivileged unconfined process to create a user namespace but restricting tasks within that namespace with a default profile. The default profile is defined in policy and has reduced permissions, if the default profile is not present apparmor will fallback to denying unconfined access to unprivileged user namespaces.
私の環境 (Ubuntu 24.04) では次の結果になりました:
unshare -U # OK
unshare -Ur # unshare: write failed /proc/self/uid_map: Operation not permitted
user namespace自体の作成はできるようですが、rootユーザーにはなれないようです。
対策
AppArmorプロファイルを作成する方法
こちらが推奨されている方法です。
/etc/apparmor.d/{profile_name} に次のファイルを作成します (profile_nameは任意のプロファイル名) :
# This profile allows everything and only exists to give the
# application a name instead of having the label "unconfined"
abi <abi/4.0>,
include <tunables/global>
# /path/to/executable は、user namespaceの制限を適用したくない実行ファイルのパス
profile profile_name /path/to/executable flags=(unconfined) {
userns,
}
そして systemctl reload apparmor.service してください。
AppArmorのカーネル設定を変更する方法
こちらは推奨されていません。AppArmorによるuser namespace制限が完全に無効になってしまうためです。
sudo sysctl kernel.apparmor_restrict_unprivileged_userns=0
感想
非特権ユーザーによるuser namespace作成の制限はセキュリティ上致し方ない部分もあると思いますが、Ubuntuとしては破壊的変更となるため「面倒な非特権コンテナはやめよう!」と、非特権コンテナから特権コンテナへの回帰の動きがあったり、AppArmor自体を無効化するような動きがあったりすると本末転倒になりかねないのではないかと懸念しています。
