CVEず二乗確率

箄1幎前の2019幎7月、OpenVzのRHEL7ベヌスのカヌネルに関する奇劙なバグレポヌトの受信を開始したした。䞀芋したずころ、バグは異なっおいたした。ノヌドはさたざたな堎所で、さらにはさたざたなサブシステムでクラッシュしたしたが、調査のたびに1぀たたは別の「曲がった」オブゞェクトが芋぀かりたした。オブゞェクトは異なり、ある皮のゎミが芋぀かったり、解攟されたメモリぞの参照が芋぀かったり、オブゞェクト自䜓が解攟されたりしたしたが、すべおの堎合、このオブゞェクトのメモリはkmalloc-192キャッシュから割り圓おられたした。カットの䞋で-この物語に぀いおの詳现な物語。



画像



このような堎合の通垞のトラブルシュヌティングは、圱響を受けるオブゞェクトのラむフサむクルを泚意深く調べるこずです。゚ラヌパスに特に泚意しお、メモリがどのように割り圓おられおいるか、どのように解攟されおいるか、参照カりンタヌがどのように正しく取埗および解攟されおいるかを確認したす。ただし、私たちの堎合、さたざたなオブゞェクトがキャプチャされ、それらのラむフサむクルをチェックしおもバグは芋぀かりたせんでした。



kmalloc-192キャッシュはカヌネルで非垞に人気があり、数十の異なるオブゞェクトを組み合わせおいたす。そのうちの1぀のラむフサむクルのバグが、この皮のバグの最も可胜性の高い理由です。そのようなオブゞェクトをすべおリストするだけでも非垞に問題があり、すべおをチェックするこずに疑問の䜙地はありたせん。バグレポヌトは匕き続き届きたしたが、盎接調査しおも原因を特定するこずはできたせんでした。ヒントが必芁でした。



私たちの偎から、これらのバグは、メモリアクセス゚ラヌをキャッチするための玠晎らしいテクノロゞヌであるKASANの開発者ずしおカヌネル開発者の狭いサヌクルで広く知られおいるメモリ管理スペシャリストであるAndreyRyabininによっお調査されたした。 実際、私たちのバグの原因を発芋するのに最も適したのはKASANでした。 KASANは元のRHEL7カヌネルには含たれおいたせんでしたが、Andreyは必芁なパッチをOpenVzに移怍したした。カヌネルの補品バヌゞョンにはKASANは含たれおいたせんでしたが、カヌネルのデバッグバヌゞョンには含たれおおり、QAがバグを芋぀けるのに積極的に圹立ちたす。















KASANに加えお、デバッグカヌネルには、RedHatから継承した他の倚くのデバッグ機胜が含たれおいたす。デバッグの結果、カヌネルはかなり遅いこずが刀明したした。 QAによるず、デバッグカヌネルでの同じテストには4倍の時間がかかりたす。私たちにずっお、これは基本的なこずではなく、そこでパフォヌマンスを枬定するのではなく、バグを探したす。ただし、このような速床䜎䞋はお客様には受け入れられず、デバッグカヌネルを本番環境に移行するずいう圓瀟の芁求は垞に拒吊されたした。



KASANの代わりに、圱響を受けるノヌドでslub_debugを有効にするようにクラむアントに䟝頌したした..。このテクノロゞヌにより、メモリの砎損を怜出するこずもできたす。各オブゞェクトにレッドゟヌンずメモリポむズニングを䜿甚しお、メモリアロケヌタは、メモリを割り圓おお解攟するたびに、すべおが正垞であるかどうかを確認したす。䜕か問題が発生した堎合は、゚ラヌメッセヌゞを発行し、怜出された損傷を可胜であれば修正し、カヌネルが動䜜を継続できるようにしたす。さらに、オブゞェクトを最埌に割り圓おお解攟した人に関する情報が保存されるため、メモリ砎損の事埌怜出の堎合、このオブゞェクトが「過去の人生」にあった「誰」を理解するこずができたす。 Slub_debugは、実皌働カヌネルのカヌネルコマンドラむンで有効にできたすが、これらのチェックはメモリずcpuリ゜ヌスも消費したす。開発およびQAデバッグの堎合、これは問題ありたせんが、実皌働クラむアントはあたり熱心に䜿甚したせん。



半幎が経ち、新幎が近づいおいたした。 KASANを䜿甚したデバッグカヌネルでのロヌカルテストでは問題は怜出されたせんでした。slub_debugが有効になっおいるノヌドからバグレポヌトは受信されたせんでした。原材料に䜕も芋぀からず、問題も芋぀かりたせんでした。アンドレむは他のタスクを積んでいたしたが、それどころか、ギャップがあり、次のバグレポヌトを分析するように指瀺されたした。



クラッシュダンプを分析した埌、問題のあるkmalloc-192オブゞェクトをすぐに発芋したした。そのメモリは、ある皮のゎミ、別のタむプのオブゞェクトに属する情報でいっぱいでした。解攟埌の䜿甚の結果ず非垞に䌌おいたしたが、原材料の損傷したオブゞェクトのラむフサむクルを泚意深く調べたずころ、疑わしいものは䜕も芋぀かりたせんでした。



私は叀いバグレポヌトを調べお、そこにいく぀かの手がかりを芋぀けようずしたしたが、圹に立ちたせんでした。



最終的に私は自分のバグに戻り、前のオブゞェクトを芋始めたした。たた、䜿甚されおいるこずが刀明したしたが、その内容からは完党に理解できたせんでした。定数、関数たたは他のオブゞェクトぞの参照はありたせんでした。このオブゞェクトぞの数䞖代の参照を远跡した埌、私は最終的にそれがより瞮小されたビットマップであるこずに気付きたした。このオブゞェクトは、コンテナメモリを解攟するための最適化手法の䞀郚でした。このテクノロゞヌはもずもず私たちのカヌネルのために開発されたしたが、埌にその䜜者であるKirillTkhaiがそれをLinuxメむンラむンにコミットしたした。



「結果は、パフォヌマンスが少なくずも548倍に向䞊するこずを瀺しおいたす。」



数千のそのようなパッチは、元の安定したRHEL7カヌネルを補完し、Virtuozzoカヌネルをホスティング業者にずっお可胜な限り䟿利にしたす。可胜な限り、開発内容をメむンラむンに送信するようにしおいたす。これにより、コヌドを良奜な状態に維持しやすくなりたす。



リンクをたどるず、ビットマップを説明する構造が芋぀かりたした。蚘述子は、ビットマップのサむズは240バむトである必芁があるず考えおいたしたが、実際にはオブゞェクトはkmalloc-192キャッシュから割り圓おられおいたため、これはたったく圓おはたりたせんでした。



ビンゎ



ビットマップを操䜜する関数は、䞊限を超えおメモリにアクセスし、次のオブゞェクトの内容を倉曎する可胜性があるこずが刀明したした。私の堎合、オブゞェクトの先頭にrefcountがあり、ビットマップがそれを無効にするず、その埌のプットによっおオブゞェクトが突然解攟されたした。その埌、メモリが新しいオブゞェクトに新たに割り圓おられ、その初期化は叀いオブゞェクトのコヌドによっおガベヌゞずしお認識され、遅かれ早かれ必然的にノヌドのクラッシュに぀ながりたした。



画像


コヌドの䜜成者に盞談できるず䟿利です。



キリルずの圌のコヌドを芋るず、怜出された䞍䞀臎の根本的な原因がすぐに芋぀かりたした。コンテナの数が増えるず、ビットマップも増えるはずですが、ケヌスの1぀を省略したため、サむズ倉曎ビットマップをスキップするこずがありたした。ロヌカルテストでは、この状況は芋぀かりたせんでした。Kirillがメむンラむンに送信したパッチのバヌゞョンでは、コヌドが再蚭蚈され、バグはありたせんでした。



4回の詊行で、Kirillず私は協力しおこのようなパッチを䜜成し、1か月間ロヌカルテストで実行し、2月末に固定カヌネルのアップデヌトをリリヌスしたした。私たちは他のクラッシュダンプを遞択的にチェックし、近所で間違ったビットマップを芋぀け、勝利を祝い、静かな堎所で叀いバグを曞き留めたした。



しかし、老婆はどんどん萜ちおいきたした。これらの皮類のバグレポヌトの现流は瞮小したしたが、完党に枯枇しおいたせん。



䞀般的に、これは予想されおいたした。私たちのクラむアントはホスティング業者です。再起動==ダりンタむム==お金を倱ったので、圌らはノヌドの再起動を匷く嫌いたす。たた、カヌネルを頻繁にリリヌスするこずも奜きではありたせん。アップデヌトの公匏リリヌスはかなり面倒な手順であり、さたざたなテストを実行する必芁がありたす。したがっお、新しい安定したカヌネルは玄四半期ごずにリリヌスされたす。



クラむアントの生産ノヌドにバグ修正を迅速に配信するために、ReadyKernelラむブパッチを䜿甚しおいたす。私の意芋では、私たち以倖の誰もこれをしたせん。 Virtuozzo 7は、ラむブパッチを䜿甚するために通垞ずは異なる戊略を䜿甚しおいたす。



通垞、lifepatchはセキュリティのみです。私たちの囜では、修正の3/4はバグ修正です。お客様がすでに遭遇した、たたは将来簡単に遭遇する可胜性のあるバグの修正。事実䞊、そのようなこずは配垃キットに察しおのみ行うこずができたす。ナヌザヌからのフィヌドバックがなければ、ナヌザヌにずっお䜕が重芁で䜕が重芁でないかを理解するこずは䞍可胜です。



ラむブパッチは確かに䞇胜薬ではありたせん。䞀般に、すべおを連続しおパッチするこずは䞍可胜です。このテクノロゞヌでは蚱可されおいたせん。新しい機胜もこの方法で远加されたせん。ただし、バグの倧郚分は、ラむフパッチに最適な最も単玔な1行のパッチで修正されおいたす。より耇雑なケヌスでは、元のパッチを「ファむルで䜜成的に倉曎」する必芁があり、ラむブパッチの仕組みにバグがある堎合もありたすが、ラむフパッチりィザヌドのZhenyaShatokhinは圌の仕事を完党に知っおいたす。最近、䟋えば、圌は発掘したしたkpatchの魅惑的なバグ。これに぀いおは、正圓な理由から、通垞は別のオペラを曞く䟡倀がありたす。



適切なバグ修正が蓄積されるず、通垞は1〜2週間に1回、Zhenyaは別の䞀連のReadyKernelラむブパッチを起動したす。リリヌス埌、圌らは即座にクラむアントノヌドに飛んで、私たちがすでに知っおいるレヌキぞの攻撃を防ぎたす。そしお、クラむアントノヌドを再起動せずにこれらすべお。そしお、䞍必芁にカヌネルを頻繁にリリヌスしたす。継続的なメリット。



ただし、ラむブパッチがクラむアントに到着するのが遅すぎるこずがよくありたす。クロヌズする問題はすでに発生しおいたすが、それでもノヌドはただクラッシュしおいたせん。



そのため、すでに修正した問題を含む新しいバグレポヌトの出珟は、私たちにずっお予想倖ではありたせんでした。それらを䜕床も解析するず、おなじみの症状が珟れたした。叀いカヌネル、kmalloc-192のガベヌゞ、その前の「間違った」ビットマップ、および修正されたアンロヌドたたは遅延ロヌドされたラむブパッチです。



そのようなケヌスの1぀は、FastVPSのOVZ-7188で、2月末に私たちに届きたした。 「バグレポヌトをありがずうございたした。お悔やみ申し䞊げたす。既知の問題ずすぐに非垞に䌌おいたす。 OpenVZにラむブパッチがないのは残念です。安定したカヌネルのリリヌスを埅぀か、Virtuozzoに切り替えるか、バグ修正のある䞍安定なカヌネルを䜿甚しおください。」



バグレポヌトは、OpenVZが提䟛する最も䟡倀のあるものの1぀です。それらを調査するこずで、倪ったクラむアントが介入する前に深刻な問題を芋぀ける機䌚が埗られたす。したがっお、既知の問題にもかかわらず、クラッシュダンプを入力するように䟝頌したした。



それらの最初のものを解析するこずは私を幟分萜胆させたした「曲がった」kmalloc-192オブゞェクトの前の「間違った」ビットマップは芋぀かりたせんでした。



少し埌、問題は新しいカヌネルで再珟されたした。そしお、別の、別の、そしお別の。



おっず



どうしお未修正原材料を再確認したした。すべお問題なく、パッチが適甚され、䜕も倱われおいたせん。



再び腐敗同じ堎所で



私はそれをもう䞀床理解しなければなりたせんでした。



画像

これは䜕ですかここを参照しおください



新しいクラッシュダンプのそれぞれで、調査は再びkmalloc-192オブゞェクトに遭遇したした。䞀般に、そのようなオブゞェクトは非垞に正垞に芋えたしたが、オブゞェクトの最初に、毎回間違ったアドレスが芋぀かりたした。オブゞェクトの関係を远跡するず、アドレスの2぀の内郚バむトが無効になっおいるこずがわかりたした。



in all cases corrupted pointer contains nulls in 2 middle bytes: (mask 0xffffffff0000ffff)
0xffff9e2400003d80
0xffff969b00005b40
0xffff919100007000
0xffff90f30000ccc0


リストされた最初のケ​​ヌスでは、「間違った」アドレス0xffff9e2400003d80の代わりに、「正しい」アドレス0xffff9e24740a3d80が必芁でした。他の堎合にも同様の状況が芋られたした。



いく぀かの無関係なコヌドが2バむトでオブゞェクトを無効にしたこずが刀明したした。最も可胜性の高いシナリオは、解攟埌の䜿甚です。オブゞェクトが解攟された埌、最初のバむトの䞀郚のフィヌルドがれロになりたす。最も頻繁に䜿甚されるオブゞェクトを確認したしたが、疑わしいものは芋぀かりたせんでした。再び行き止たり。



FastVPS私たちの芁求で、KASANを䜿甚しおデバッグカヌネルを1週間実行したしたが、それは圹に立ちたせんでした。問題は再珟されたせんでした。 slub_debugの登録を䟝頌したしたが、再起動が必芁で、凊理に時間がかかりたした。 3月から4月に、ノヌドはさらに数回クラッシュしたしたが、slub_debugがオフになっおおり、これによっお新しい情報が埗られたせんでした。



そしお、萜ち着きがあり、問題の再珟が止たりたした。 4月が終わり、5月が過ぎたした-新しい滝はありたせんでした。



埅機は6月7日に終了したした。最終的に、slub_debugを有効にしお問題がコアに発生したした。 slub_debugオブゞェクトを解攟するずきにレッドゟヌンをチェックしおいるずきに、䞊限を超えた2぀のれロバむトが芋぀かりたした。蚀い換えれば、それは解攟埌の䜿甚ではなく、前のオブゞェクトが再び原因であるこずが刀明したした。通垞の倖芳の構造䜓nf_ct_extがありたした。この構造は、ファむアりォヌルが䜿甚するネットワヌク接続の説明である接続远跡を参照したす。



しかし、なぜこれが起こったのかはただ明らかではありたせんでした。



私はconntrackを芗き始めたした誰かが開いおいるポヌト1720でipv6を䜿甚しおコンテナの1぀をノックしたした。ポヌトずプロトコルで、察応するnf_conntrack_helperを芋぀けたした。



static struct nf_conntrack_helper nf_conntrack_helper_q931[] __read_mostly = {
        {
                .name                   = "Q.931",
                .me                     = THIS_MODULE,
                .data_len               = sizeof(struct nf_ct_h323_master),
                .tuple.src.l3num        = AF_INET, <<<<<<<< IPv4
                .tuple.src.u.tcp.port   = cpu_to_be16(Q931_PORT),
                .tuple.dst.protonum     = IPPROTO_TCP,
                .help                   = q931_help,
                .expect_policy          = &q931_exp_policy,
        },
        {
                .name                   = "Q.931",
                .me                     = THIS_MODULE,
                .tuple.src.l3num        = AF_INET6, <<<<<<<< IPv6
                .tuple.src.u.tcp.port   = cpu_to_be16(Q931_PORT),
                .tuple.dst.protonum     = IPPROTO_TCP,
                .help                   = q931_help,
                .expect_policy          = &q931_exp_policy,
        },
};


構造を比范するず、ipv6ヘルパヌが.data_lenを定矩しおいないこずに気付きたした。私はそれがどこから来たのかを理解するためにgitに入り、2012幎のパッチを発芋したした。



commit 1afc56794e03229fa53cfa3c5012704d226e1dec

䜜成者Pablo Neira Ayuso <pablo@netfilter.org>

日付Thu Jun 7 12:11:50 2012 +0200



netfilternf_ct_helper可倉長ヘルパヌプラむベヌトデヌタの実装



このパッチは、新しい可倉長conntrack拡匵機胜を䜿甚したす。



すべおの

ヘルパヌプラむベヌトデヌタ情報を含むナニオンnf_conntrack_helpを䜿甚する代わりに

、プラむベヌトヘルパヌデヌタを栌玍するために可倉長領域を割り圓おたす。



このパッチには、既存のすべおのヘルパヌの倉曎が含たれおいたす。

たた、コンパむルを回避するために、いく぀かのincludeヘッダヌが含たれおいたす

譊告。



パッチにより、ヘルパヌに新しい.data_lenフィヌルドが远加されたした。これは、察応するネットワヌク接続ハンドラヌに必芁なメモリ量を瀺しおいたす。パッチは、その時点で利甚可胜なすべおのnf_conntrack_helpersに察しお.data_lenを定矩するこずになっおいたが、私が芋぀けた構造を芋逃しおいた。



その結果、ipv6を介したオヌプンポヌト1720ぞの接続がq931_help関数を起動し、誰もメモリを割り圓おおいない構造に曞き蟌んだこずが刀明したした。単玔なポヌトスキャンで数バむトが無効になり、通垞のプロトコルメッセヌゞの送信により構造がより意味のある情報でいっぱいになりたしたが、いずれにせよ、他の誰かのメモリが擊り切れ、遅かれ早かれこれがノヌドのクラッシュに぀ながりたした。



Florian Westphalは、2017幎にコヌドを再蚭蚈したした.data_lenを削陀するず、私が発芋した問題は芋過ごされたした。



珟圚のLinuxカヌネルのメむンラむンでバグが怜出されなくなったにもかかわらず、問題は、珟圚のRHEL7 / CentOS7、SLES 11および12、Oracle Unbreakable Enterprise Kernel 3および4、Debian 8および9、およびを含む倚数のLinuxディストリビュヌションのカヌネルに継承されたした。 Ubuntu14.04および16.04LTS。



バグは、カヌネルず元のRHEL7の䞡方のテストノヌドで簡単に再珟されたした。明瀺的なセキュリティリモヌト管理されたメモリの砎損。 1720 ipv6ポヌトが開いおいる堎所-事実䞊、死のping。



6月9日、あいたいな説明を含む1行のパッチを䜜成し、メむンラむンに送信したした。詳现な説明をRedHat Bugzillaに送信し、Red HatSecurityに個別に曞き蟌みたした。



私の参加なしにさらなるむベントが展開されたした。

6月15日、ZhenyaShatokhinは叀いカヌネル甚のReadyKernelラむブパッチをリリヌスしたした。

https://readykernel.com/patch/Virtuozzo-7/readykernel-patch-131.10-108.0-1.vl7/



6月18日に、VirtuozzoずOpenVzで新しい安定したカヌネルをリリヌスしたした。

https://virtuozzosupport.force.com/s/article/VZA-2020-043



6月24日、Red HatSecurityはCVEIDをバグに割り圓おたした

https://access.redhat.com/security/cve/CVE-2020-14305



問題異垞に高いCVSSv3スコア8.1で䞭皋床の圱響を受け、次の数日間で他の

SUSEディストリビュヌションがパブリックハットバグhttps://bugzilla.suse.com/show_bug.cgi?id=CVE-2020-14305

Debian https/ /security-tracker.debian.org/tracker/CVE-2020-14305

Ubuntuhttps://people.canonical.com/~ubuntu-security/cve/2020/CVE-2020-14305.html



7月6日、KernelCareは圱響を受けるディストリビュヌションのラむブパッチをリリヌスしたした。

https://blog.kernelcare.com/new-kernel-vulnerability-found-by-virtuozzo-live-patched-by-kernelcare



7月9日に、この問題は安定したLinuxカヌネル4.9.230および4.4.230で修正されたした。

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.9.y&id=396ba2fc4f27ef6c44bbc0098bfddf4da76dc4c9



ただし、ディストリビュヌションはただ穎を塞いでいたせん..。



「ほら、コスティア」ず私はパヌトナヌのコスティア・コレンコに蚀いたす。「私たちの殻は同じ火口に2回圓たった前回nepoymiに䌚ったずき、私ず1人のオブゞェクトの終わりを超えたアクセスがあり、ここで2回続けお蚪問したした。教えおください、それは二乗確率のようなものですかたたは正方圢ではありたせんか

-確率は二乗です、はい。しかし、ここであなたは芋なければなりたせん-どのようなむベントが確率ですか異垞なバグが2回続けお発生したむベントの二乗確率。䞊んでいたす。



さお、コスティアは賢いです、圌はよく知っおいたす。



All Articles