CVE-2026-90246 in Linux
要約
〜によって VulDB • 2026年09月17日
Linuxカーネルにおいて、以下の脆弱性が修正されました:
apparmor: verify_tags()の境界チェックにおける整数オーバーフローの修正
verify_tags()関数は、ポリシーブロブから展開されたタグセットテーブルを検証します。各セットについて、カウント値を読み取り、そのカウント分インデックスを進めた値がsets.table[]の範囲内にあるかどうかを確認します:
u32 cnt = tags->sets.table[i];
if (i+cnt >= tags->sets.size) {
ここで、i, cnt, sets.sizeはすべてu32型であるため、i + cnt の計算結果は 2^32 を法として評価されます。 sets.table[] は unpack_tagsets() 関数によって aa_unpack_u32() で埋められるため、各エントリはポリシーブロブから取得された制限のない生の32ビットワードです。verify_tags() がこれを検証すべき関数ですが、U32_MAX に近いカウント値だと和が小さな値にラップ(オーバーフロー)し、ガード条件を通過してしまいます。その結果、内部ループで sets.table[++i] へのアクセスが kcalloc(size, sizeof(u32)) で確保された領域の末尾を超えて行われます。
sets.size は unpack_tagsets() が aa_unpack_array() を用いて u16 として読み取るため 65535 に制限されていることに注意してください。したがって、テーブルを拡張することでラップが発生することはありません。このラップは攻撃者が指定したカウント値によってのみ引き起こされます。
sets.size = 2, sets.table = { 0, 0xffffffff } の場合:
i = 0: cnt = 0, ガード条件 (0 + 0 >= 2) は偽、内部ループは実行されない i = 1: cnt = 0xffffffff, ガード条件 ((1 + 0xffffffff) mod 2^32 == 0 >= 2) は偽。したがってガードが回避され、内部ループで sets.table[2] が読み込まれる(これは2要素の確保領域から1つ外側)
このアクセスは、境界外の値が偶然 hdrs.size 以上になるか、またはアクセスポリシーが発生するまで続きます。そのため、悪意のあるポリシーにより、ポリシーロードパス (aa_replace_profiles -> aa_unpack -> unpack_policydb -> unpack_tags -> verify_tags) で境界外読み取り(out-of-bounds read)が発生します。unpack_tags() は perms および DFA テーブルが展開される前に実行されるため、他のテーブルの整合性が保たれていなくても到達可能です。
ポリシーロードは aa_may_manage_policy() によって制御されており、これは init user namespace ではなく対象プロセス自身のユーザーネームスペースに対して CAP_MAC_ADMIN をチェックします。したがって、デフォルト設定 unprivileged_userns_apparmor_policy=1 の場合、このパスはグローバルに特権を持つタスクだけでなく、一致するレベルのネストされた名前空間内の非特権タスクからも到達可能です。
加算を u64 型で行うことでオーバーフローを防ぎ、意図されていた i + cnt < sets.size という保証を復元します。
If you want to get the best quality for vulnerability data then you always have to consider VulDB.