Linux KernelのLPE(Local Privilege Escalation)脆弱性(Dirty Frag: CVE-2026-43284, CVE-2026-43500)

05/08/2026にLinux KernelのLPE(Local Privilege Escalation)脆弱性(Dirty Frag: CVE-2026-43284, CVE-2026-43500)が公開されました。9年前からxfrm-ESP/rxRPCモジュールに脆弱性がある模様です。Dirty PipeやCopy Failと似たような脆弱性ですが、タイミング攻撃では無いため厄介な模様です。PoCも公開されています。また、本脆弱性は意図せず公開がされてしまった模様で、CVEも未アサインの状態です。今回はこちらの脆弱性の概要と、各ディストリビューションの対応について纏めます。

(2026/05/08 17:00 追記) CVE-2026-43284が割り当てられた模様です。

(2026/05/08 17:00 追記) CVE-2026-43500も割当られる模様です。

[過去関連リンク(最新5件)]

一次情報源

Dirty Frag: Universal Linux LPE

影響するバージョン

問題となっているモジュールのソースコードがLinux Kernelのアップストリームに追加されたのが9年前ということで、9年前(2017年ごろ)以降のLinux Kernelに脆弱性があるモジュールが含まれています。

少なくとも、以下の環境ではこの脆弱性があることがテストにより判明している模様です

  • Ubuntu 24.04.4: 6.17.0-23-generic
  • RHEL 10.1: 6.12.0-124.49.1.el10_1.x86_64
  • openSUSE Tumbleweed: 7.0.2-1-default
  • CentOS Stream 10: 6.12.0-224.el10.x86_64
  • AlmaLinux 10: 6.12.0-124.52.3.el10_1.x86_64
  • Fedora 44: 6.19.14-300.fc44.x86_64

CVE概要(詳細はCVEのサイトをご確認ください)

https://www.cve.org/CVERecord?id=CVE-2026-43284

https://www.cve.org/CVERecord?id=CVE-2026-43500

CVSS/プライオリティ

情報が出て来次第更新します。

修正方法

CVE-IDアサイン後に情報が出ると思いますので、その際に更新します。各ディストリビューションの情報を確認してください。

緩和策

脆弱性が存在するモジュールを削除することで脆弱性が迂回できます。下記のコマンドになります。詳しい情報は一次情報源を参照してください。

sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf; rmmod esp4 esp6 rxrpc 2>/dev/null; true"

脆弱性概要(詳細はこちらのサイトをご確認ください)

以下は一次情報源から引用して適宜翻訳したものになります。ExploitやPoCに関しては、こちらのサイトには(意図して)載せませんので、一次情報源を確認してください。

Dirty FragはDirty PipeやCopy Failと似たような脆弱性です。Dirty Pipeではpipe_buffer()構造体を上書きしていましたが、Dirty Fragではsk_buff()構造体のfragを上書きします。Copy Failではspliceを用いて攻撃者によるPage Cache PageをTX SGLに仕込みますが、Dirty Fragでは、spliceによる非線形skbのfragで、同じ様なパターンが再現されてしまう脆弱性です。

  • xfrm-ESP Page-Cache Write
  • RxRPC Page-Cache Write

の2つに脆弱性が存在します。

xfrm-ESP Page-Cache Write

ESPペイロードのAEAD暗号の復号化をin-placeで行う前に、esp_input()skb_cow_data()を用いて新たなカーネルプライベートバッファーを割り当てる必要があります。skbが非線形データ領域だった場合、フラグ化されたデータをコピーした後にin-place操作を行います。しかし、問題があるパッチが当てられた結果、Copy on writeをバイパスすることができるようになっていました。

static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
{
        [...]

        if (!skb_cloned(skb)) {
                if (!skb_is_nonlinear(skb)) {    // <=[1]
                        nfrags = 1;

                        goto skip_cow;
                } else if (!skb_has_frag_list(skb)) {
                        nfrags = skb_shinfo(skb)->nr_frags;
                        nfrags++;

                        goto skip_cow;           // <=[2]
                }
        }

        err = skb_cow_data(skb, 0, &trailer);

        [...]

[1]でskbにフラグデータがあったとしても、frag_listが存在しない場合には[2]に直接ジャンプしてしまい、フラグデータのトップでin-placeのcrypto操作を実行してしまいます。

問題はin-placeでのcrypto操作にあるのではなく、in-placeでのcypto操作の結果によるSTOREにあります。ESP + ESN + authencesn(...)の組み合わせでcrypto_authenc_esn_decrypt()は前処理の際にシーケンス番号の上位4バイトをsrc SGLの末尾へ移動させる以下のSTORE処理を実行します。

static int crypto_authenc_esn_decrypt(struct aead_request *req)
{
        [...]

        /* Move high-order bits of sequence number to the end. */
        scatterwalk_map_and_copy(tmp, src, 0, 8, 0);
        if (src == dst) {
                scatterwalk_map_and_copy(tmp, dst, 4, 4, 1);
                scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);   // <=[3]
                dst = scatterwalk_ffwd(areq_ctx->dst, dst, 4);
        [...]

[3]での4バイトSTOREがdst SGLでのassoclen + cryptlen位置で行われます。攻撃者がペイロード長を調整し、splice経由で配置されたページPがその位置になるようにした場合には、その4バイトはページP内の意図したファイルオフセット位置に格納されることになります。

これら4バイトの値は、tmp + 1が指すデータ、つまりESPヘッダ内のシーケンス番号の上位32ビットに相当します。この値がどこからきたのかをトラッキングすると、esp_input_set_header()関数は単にSAのXFRM_SKB_CB(skb)->seq.input.hiを所定の位置にコピーしているに過ぎず、実体はreplay_esn->seq_hiであり、これはSA登録時にユーザがXFRMA_REPLAY_ESN_VAL Netlink属性を通じて任意に指定しできる値になります。

static void esp_input_set_header(struct sk_buff *skb, __be32 *seqhi)
{
        struct xfrm_state *x = xfrm_input_state(skb);
        struct ip_esp_hdr *esph;

        /* For ESN we move the header forward by 4 bytes to
         * accommodate the high bits.  We will move it back after
         * decryption.
         */
        if ((x->props.flags & XFRM_STATE_ESN)) {
                esph = skb_push(skb, 4);
                *seqhi = esph->spi;
                esph->spi = esph->seq_no;
                esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi;
        }
}

したがって、攻撃者はSTOREの場所 (ファイル オフセット) と値 (4 バイト) の両方を制御できます。AEAD認証の検証はSTOREの後に実行されるため、認証が失敗した場合でもSTOREは既に実行されており、ページ キャッシュの変更は保持されます。言い換えれば、攻撃者はSAの認証キーを知らなくても変更に成功します。さらに、esp_input を呼び出すにはXFRM SAを登録する必要があり、それにはCAP_NET_ADMINが必要です。つまり、攻撃者はUser Namespaceを作成する権限が必要になります。

RxRPC Page-Cache Write

RXKAD(RxRPC Kerberos Authentication Domain)セキュリティクラスのRXRPC_SECURITY_AUTHレベルでのデータパケットを検証する際に、rxkad_verify_packet_1()がin-placeでpcbc(fcrypt)複号をskbのrxpcペイロードでの先端8バイトで実行します。

static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
                                 rxrpc_seq_t seq,
                                 struct skcipher_request *req)
{

        [...]

        /* Decrypt the skbuff in-place.  TODO: We really want to decrypt
         * directly into the target buffer.
         */
        sg_init_table(sg, ARRAY_SIZE(sg));
        ret = skb_to_sgvec(skb, sg, sp->offset, 8);
        if (unlikely(ret < 0))
                return ret;

        /* start the decryption afresh */
        memset(&iv, 0, sizeof(iv));

        skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
        skcipher_request_set_callback(req, 0, NULL, NULL);
        skcipher_request_set_crypt(req, sg, sg, 8, iv.x);     // <=[4]
        ret = crypto_skcipher_decrypt(req);                   // <=[5]

[4]で、srcとdstのSGLは同じになり、in-placeで実行されます。skb_to_sgvec()がskbのフラグデータを直接SGLに変換する際に、攻撃者がspliceを用いてフラグに固定したページキャッシュPはそのままSGLのsrc/dstになります。[5]で、Pの上で8-byteのSTOREが実行されます。

xfrm-ESP Page-Cache Write との違いは、STOREの値が攻撃者が直接制御する 4 バイトではなく、攻撃者の鍵Kで一度暗号化した8バイトである点です。IVが0でブロックが1つであるため、pcbc_decrypt(C, K, IV=0) はfcrypt_decrypt(C, K) と同等です。つまり、STOREに格納される8バイトは fcrypt_decrypt(C, K) の結果であり、攻撃者はKを変更し続けてユーザー空間で総当たり攻撃を仕掛けることで、目的の8バイトの平文が出現するまで攻撃を続けることができます。

fcryptは、Andrewファイルシステム用の暗号化関数で、56ビットの鍵と8バイトのブロックサイズを使用し、ユーザー空間に移植可能です。

暗号化関数 tfm()で使用されるKは、add_key(“rxrpc”, desc, payload, …, KEY_SPEC_PROCESS_KEYRING)で登録されたRxRPC v1トークンのsession_keyフィールドから取得出来ます。RxRPCキーの登録には特権は不要なので、特権を持たないユーザーでもKを自由に制御できます。

PoC

一次情報源にPoC及び動画があります。

主なディストリビューションの対応方法

CVE-IDがアサインされ、ディストリビューションが対応次第更新します。詳細は、各ディストリビューションの提供元にご確認ください

(2026/05/08 17:00 更新: CVE-2026-43284を追加)

(2026/05/08 18:00 更新: CVE-2026-43500を追加)

対処方法

各ディストリビューションの案内に従い、アップデートを行ってください。

[参考]

タイトルとURLをコピーしました