Upgrade to Pro — share decks privately, control downloads, hide ads and more …

トラブルシューティングから Linux カーネルに潜り込む

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

トラブルシューティングから Linux カーネルに潜り込む

Avatar for Hiroya Ito

Hiroya Ito

May 24, 2023
Tweet

More Decks by Hiroya Ito

Other Decks in Technology

Transcript

  1. 2 自己紹介 GMOペパボ セキュリティ対策室 2007年 入社 伊藤 洋也 Hiroya Ito

    ホスティングサービス、技術基盤チームを経て 現在はセキュリティ対策室に所属 • GitHub, Twitter : @hiboma • https://hiboma.hatenadiary.jp/
  2. 4 登壇の打診をいただいたが、私の場合どんな話をできるだろうか ? 🤔 • Linux カーネルコミッターではないしなぁ ... • Linux

    カーネルの開発業務も経験がないしなぁ ... * • Linux カーネルのトラブルシューティングは時々やってる 💡 『達人に聞く、Linux カーネルコードの歩き方』 注) 検証や調査のカーネルモジュールやパッチを書くことはあリます。でも production で動かすコードを書くことは全然無いです
  3. 5 自社サービスの運用で Linux カーネルの問題に遭遇する 🔥 • パフォーマンスの劣化 • カーネルパニック •

    メモリリーク • レースコンディション • デッドロック • 脆弱性 • ハードウェアとの互換性問題 * • ... etc Linux カーネルのトラブルシューティング 注) 業務でサーバ構築やハードウェアの保守に携わる機会が無く、私個人はハードウェア / ドライバ周りのトラブル対応経験が全然ありません
  4. 6 • 問題を解決 (緩和) するため * • 問題を再現するため • 再現のヒントを得たい

    • 問題を理解するため • 理解したうえで同僚にも説明したい • 問題の再発防止のため • 監視に使えるデータを探したり • 単純に実装に興味がある 🌝 注) カーネルのアップデート、ワークアラウンドの実施、サーバの構成変更して 「解決」するケースが多いです。パッチを送って upstream から解決! ... は未経験 トラブルシューティングで Linux カーネルコードまで潜り込む動機
  5. 8 GMOペパボの SaaS サービス /ホスティングサービスを提供する Linux サーバが対象です • オンプレミス環境のカーネル •

    プライベートクラウド (OpenStack / KVM ) 環境 • ゲスト VM のカーネル • ホストマシンのカーネル • パブリッククラウド環境のカーネル トラブルシューティング事例の舞台
  6. 10 環境 (OpenStack) • ゲストに vCPU (仮想CPU) をたくさんはやした VM (

    mysqld ) がいた • ホストで wazuh のプロセス* がセキュリティチェックで様々なファイルを read(2) してた • 📝 ホストは Ubuntu Xenial で 4.4系カーネル 症状 • ゲスト VM 内の mysqld の監視で、接続断を知らせるアラートが時々出ていた • 同時にホストの CPU %system がスパイクしていた 注) https://wazuh.com/ ファイルの整合性監視などを備えた XDR SIEM を提供するセキュリティプラットフォーム ( OSS もあります ) トラブルシューティング事例 (1) CPU %system がスパイク
  7. 11 問題 • 1. ゲスト VM でページフォルトが発生する • tdp_page_fault() で

    struct kvm の mmu_lock を取ろうとする • 2. wazuh がファイルを read(2) まくり -> Free なメモリが減り slab の回収処理が走る • mmu_shrink_scan() で struct kvm の mmu_lock を取ろうとする • 1, 2 が並行してスピンロックが競合 🔥 解決 • wazuh を cgroup のメモリ制限化に入れた • slab 回収処理が cgroup 内だけで走るようにして ページフォルトと競合しないようにした トラブルシューティング事例 (1) CPU %system がスパイク
  8. 14 環境 (OpenStack ) • ゲスト CentOS 3.10.0-693.17.1.el7.x86_64 (問題のカーネル) •

    ホスト Ubuntu 4.4.0-119-generic 症状 • 3.10.0-693.17.1.el7.x86_64 の VM でなぜか CPU %user が高い 🔥 • 冗長化したロールでカーネルバージョンが混在しており、このバージョンだけ異常を示していた • このカーネルの VM が起動すると、なぜか 同じホストの他 VM でも CPU %user が高くなる トラブルシューティング事例(2) CPU %user がスパイクする 2018年の Spectre / Meltdown 脆弱性対応の修正カーネルがどんどん出ていた頃の話
  9. 15 問題 • kernel-3.10.0-693.17.1.el7.x86_64 の IBRS * の扱いにバグがあった • 勝手に

    IBRS 機能を有効 ( sysctl kernel.ibrs_enabled=1 相当) にしてしまう • 💡 IBRS で Specter V2 の脆弱性を緩和できたのだが 、CPU パフォマーンスが低下する副作用 があった • 💡 後々、RHSA-2018:2216 としてセキュリティアドバイザリも出ていた 解決 • kernel-3.10.0-693.17.1.el7.x86_64 を使っていた VM 全台でカーネルを更新 • 1台でも起動すると問題が再発するので根絶しないといけなかった • 💀 VM を 別のホストに live-migration すると症状が <伝染> する ... という問題にもなっていたので <根絶> が必要 注) IBRS(Indirect Branch Restricted Speculation:間接分岐の投機的実行機能に対する制約の付加) トラブルシューティング事例(2) CPU %user がスパイクする
  10. 17 cgroup を作るとslab の sysfs ファイルが生えるが、cgroup を消しても sysfs ファイルが残るバグに遭遇 トラブルシューティング事例(3)

    sysfs のファイルがリークする root@bionic:~# find /sys/kernel/ -type d | grep hogehoge /sys/kernel/slab/radix_tree_node/cgroup/radix_tree_node(987:hogehoge-1) /sys/kernel/slab/dentry/cgroup/dentry(1029:hogehoge-4) /sys/kernel/slab/dentry/cgroup/dentry(1027:hogehoge-3) /sys/kernel/slab/dentry/cgroup/dentry(1025:hogehoge-2) /sys/kernel/slab/dentry/cgroup/dentry(1039:hogehoge-9) /sys/kernel/slab/dentry/cgroup/dentry(1023:hogehoge-1) .... コンテナ環境を提供するホスティングサービスで遭遇。サービスに特は影響はしていなかったが不可思議で調べた。
  11. 19 dmesg に出てるログを調べるケース。これも よくありますね トラブルシューティング事例(4) : TCP: out of memory

    Dec 17 07:27:02 proxy000 kernel: [ 9774.254080] TCP: out of memory -- consider tuning tcp_mem Dec 17 07:27:02 proxy000 kernel: [ 9774.399771] TCP: out of memory -- consider tuning tcp_mem Dec 17 07:27:02 proxy000 kernel: [ 9774.401927] TCP: out of memory -- consider tuning tcp_mem Dec 17 07:27:02 proxy000 kernel: [ 9774.900174] TCP: out of memory -- consider tuning tcp_mem Dec 17 07:27:03 proxy000 kernel: [ 9775.152904] TCP: out of memory -- consider tuning tcp_mem
  12. 20 環境 (OpenStack ) • haproxy を載せた VM • OpenStack

    の L7 ロードバランサーサービス Octavia として動いていた 症状 • haproxy を介しての TCP のデータ送受信が極端に遅い / 接続が切れる • 同時に TCP: out of memory -- consider tuning tcp_mem の dmesg も出ていた トラブルシューティング事例(4) : TCP: out of memory
  13. 21 解決 • net.ipv4.tcp_mem をチューニングして解決 * 発展の課題 • 問題自体は解決したが ...

    気になることが多い 🤔 • net.ipv4.tcp_mem は TCP にどう作用するチューニングパラメータなのか ? • TCP out of memory になると カーネル内部で何が起きるのか ? • /proc/net/* 以下のどの数値を見たら監視できるのか ? 同僚の @pyama さんが シュっと調べて直してくれた トラブルシューティング事例(4) : TCP: out of memory
  14. 24 • 問題のありそうな関数やログを端緒にコードを眺める • 素朴に grep * や GNU Global

    で読んでいる • コードを 全部 理解しようとはしない。大変 🌝 • 細部は読み飛ばして、大枠をつかめば問題解決に辿り着けることも • たまに、読み飛ばした部分が重要だったりすることが ... ウワー トラブルシューティングで Linux カーネルコードリーディング 注) 素の grep を使うわけでなくパターンマッチさせて検索するという意味
  15. 25 • dmesg のログ • perf コマンド • /proc/$pid/wchan や

    /proc/$pid/stack • /proc/* とか /sys/* とかのファイル • sysrq-trigger でダンプ • strace , gdb • メトリクス • ... etc プロファイルとったり、コードを探るためのログやカーネルの関数や統計などを探していく Linux カーネルのトラブルシューティングで 見るもの / 使うもの
  16. コードを読みつつ、情報収集 • 現行バージョンと upstream との差分をみる • パッチ、コミットログを漁る • 発表スライドを見る •

    バグトラッカーを見る • ベンダーのサポートページを見る • ブログを読む • 文献にあたる • ... etc 2023年なら ChatGPT も選択肢かな? 26 トラブルシューティング コードを追いつつ情報収集
  17. 27 いろいろ情報集めても確信を得られない時 • 「ほんとに ここが問題のコードなのかな ? 🤔」 • 「Web でそれっぽい解説や解決方法を見つけたけど、一緒の問題なんだろうか

    🤔」 • 「パッチを見つけたけど、これでほんとに直るのかな ... 🤔 」 確信が得られるまでコード読み直したり情報収集をやり直す * トラブルシューティング 難しいところ 注) 開発環境で問題が再現できれば、確証を得るために試行錯誤できますね。本番環境でしか問題が起きないケースが難しい ... !
  18. 28 • 問題を解決できるとうれしい • サービス / システムが安定するとうれしい • 「自分のアプローチや仮説は確かに合っていたんだな!」という充実感もある •

    教科書的でない角度から Linux カーネルの理解できる • 調べたり試したことが自分の中で「 Linux カーネルのモデル *」として定着する トラブルシューティング やりがい 注) メンタルモデルというか、脳内でのトイモデルというか
  19. セクションタイトル 32 何を端緒にカーネルに潜っていくか ? • CPU のメトリクス • dmesg のログ

    • メモリのメトリクス • I/O のメトリクス • 可観測ツールの情報 • /proc 以下の情報 • ... トラブルシューティングからのカーネルコードへのエントリー
  20. セクションタイトル 33 STATE D (TASK_UNINTERRUPTIBLE) なプロセスが出て %iowait が刺さるケース。よく遭遇する トラブルシューティング事例 :

    %iowait CPU が刺さるケース いろんなケースがあるが、XFS のバグで shrink_slab でデッドロックするケースを例に挙げた https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=7a29ac474a47eb8cf212b45917683ae89d6fa13b
  21. セクションタイトル 35 環境 (OpenStack) • vCPU をたくさん生やした GitHub Enterprise Server

    (*) が VM で動いていた 症状 • 業務時間帯やバックアップを採取する時間に Web UI が重い • %system CPU も慢性的に高い状態 注) “GitHub Enterprise Server は、エンタープライズ内のソフトウェア開発用のセルフホステッド プラットフォームです ” ( オンプレ のVM で動く GitHub ) トラブルシューティング : %system CPU が慢性的に高い
  22. セクションタイトル 36 問題 • perf で調べたら ホストの tdp_page_fault() でスピンロックが競合しまくっていた 🔥

    • struct kvm の mmu_lock() 獲得部分 解決 • tdp_page_fault() 周りのパフォーマンス改善が入った upstream の情報を見つけた • Linux 5.15 KVM Defaults To The New x86 TDP MMU, Enables AMD SVM 5-Level Paging - Phoronix • ホストのカーネルアップデートで改善できた トラブルシューティング : %system CPU が慢性的に高い 注) もしかしたら、一つ前の事例も同様のボトルネックだったかもしれない ? けど深追いできておらず
  23. セクションタイトル 38 たまに遭遇する気がする : slab キャッシュがリークする トラブルシューティング : slab キャッシュのリーク

    SUnreclaim な slab ( kmalloc-256, Acpi-Operand ) がリークしてたケース。 調べてみたけどよく分からず、カーネルのバージョンをあげたら再発しなくなった ( Ubuntu Bionic )
  24. セクションタイトル 39 dmesg に出てるログを調べるケース。よく遭遇する トラブルシューティング : dmesg のログから [4946925.516514] INFO:

    task ip:1747 blocked for more than 120 seconds. [4946925.516558] Not tainted 4.4.0-137-generic #163-Ubuntu [4946925.516599] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [4946925.516666] ip D ffff8819d1f17dc8 0 1747 1746 0x00000080 [4946925.516671] ffff8819d1f17dc8 ffff882118dae840 ffff883ff0c27000 ffff8801c4602a00 [4946925.516674] ffff8819d1f18000 ffffffff81efc764 ffff8801c4602a00 00000000ffffffff [4946925.516676] ffffffff81efc768 ffff8819d1f17de0 ffffffff818511b5 ffffffff81efc760 [4946925.516679] Call Trace: [4946925.516689] [<ffffffff818511b5>] schedule+0x35/0x80 [4946925.516692] [<ffffffff8185145e>] schedule_preempt_disabled+0xe/0x10 [4946925.516695] [<ffffffff81853099>] __mutex_lock_slowpath+0xb9/0x130 [4946925.516698] [<ffffffff8185312f>] mutex_lock+0x1f/0x30 [4946925.516704] [<ffffffff8173ce4e>] copy_net_ns+0x6e/0x120 [4946925.516710] [<ffffffff810a5b1b>] create_new_namespaces+0x11b/0x1d0 [4946925.516713] [<ffffffff810a5d5a>] unshare_nsproxy_namespaces+0x5a/0xb0 [4946925.516718] [<ffffffff81084461>] SyS_unshare+0x1f1/0x3a0 [4946925.516721] [<ffffffff8185538e>] entry_SYSCALL_64_fastpath+0x22/0xc1 ... 同様のログがたくさん
  25. セクションタイトル 40 トラブルシューティング : dmesg のログから Jun 20 21:07:18 example

    kernel: [32668670.771896] BUG: unable to handle kernel paging request at 00000000b068c000 Jun 20 21:07:18 example kernel: [32668670.774197] IP: [<ffffffffc0241df7>] kvm_zap_rmapp+0x47/0x60 [kvm] Jun 20 21:07:18 example kernel: [32668670.777209] Oops: 0000 [#1] SMP Jun 20 21:07:18 example kernel: [32668671.052705] Call Trace: Jun 20 21:07:18 example kernel: [32668671.058576] [<ffffffffc0241e1e>] kvm_unmap_rmapp+0xe/0x20 [kvm] Jun 20 21:07:18 example kernel: [32668671.064464] [<ffffffffc023fe5d>] kvm_handle_hva_range+0x12d/0x190 [kvm] Jun 20 21:07:18 example kernel: [32668671.070332] [<ffffffffc0249fc7>] kvm_unmap_hva_range+0x17/0x20 [kvm] Jun 20 21:07:18 example kernel: [32668671.076150] [<ffffffffc0224633>] kvm_mmu_notifier_invalidate_range_start+0x53/0x90 [kvm] Jun 20 21:07:18 example kernel: [32668671.087460] [<ffffffff811e5d35>] __mmu_notifier_invalidate_range_start+0x55/0x80 Jun 20 21:07:18 example kernel: [32668671.098756] [<ffffffff811cae3c>] change_protection_range+0x79c/0x830 Jun 20 21:07:18 example kernel: [32668671.104506] [<ffffffffc0223327>] ? kvm_vcpu_ioctl+0x137/0x620 [kvm] Jun 20 21:07:18 example kernel: [32668671.110159] [<ffffffff811caee4>] change_protection+0x14/0x20 Jun 20 21:07:18 example kernel: [32668671.115703] [<ffffffff811e367c>] change_prot_numa+0x1c/0x40 Jun 20 21:07:18 example kernel: [32668671.121112] [<ffffffff810b2efb>] task_numa_work+0x1fb/0x2f0 Jun 20 21:07:18 example kernel: [32668671.126412] [<ffffffff8109f001>] task_work_run+0x81/0xa0 Jun 20 21:07:18 example kernel: [32668671.131573] [<ffffffff81003242>] exit_to_usermode_loop+0xc2/0xd0 Jun 20 21:07:18 example kernel: [32668671.136652] [<ffffffff81003c6e>] syscall_return_slowpath+0x4e/0x60 Jun 20 21:07:18 example kernel: [32668671.141683] [<ffffffff8183c7d0>] int_ret_from_sys_call+0x25/0x8f Jun 20 21:07:18 example kernel: [32668671.161698] RIP [<ffffffffc0241df7>] kvm_zap_rmapp+0x47/0x60 [kvm]