Linux システムによって報告される tcp_mark_head_lost エラーの処理方法

Linux システムによって報告される tcp_mark_head_lost エラーの処理方法

問題の説明

最近、ホストから次のカーネル情報が報告されました。

7月8日 10:47:42 cztest カーネル: ------------[ここでカット]------------
7月8日 10:47:42 cztestカーネル: 警告: net/ipv4/tcp_input.c:2269 tcp_mark_head_lost+0x113/0x290()
7 月 8 日 10:47:42 cztest カーネル: リンクされているモジュール: iptable_filter ip_tables binfmt_misc cdc_ether usbnet mii xt_multiport dm_mirror dm_region_hash dm_log dm_mod intel_powerclamp coretemp intel_rapl iosf_mbi kvm_intel kvm irqbypass crc32_p
clmul ghash_clmulni_intel aesni_intel lrw gf128mul glue_helper ablk_helper cryptd ipmi_ssif ipmi_devintf ipmi_si mei_me pcspkr iTCO_wdt mxm_wmi iTCO_vendor_support dcdbas mei sg sb_edac edac_core ipmi_msghandler shpchp lpc_ich wmi acpi_p
ower_meter xfs libcrc32c sd_mod crc_t10dif crct10dif_generic mgag200 drm_kms_helper crct10dif_pclmul crct10dif_common syscopyarea crc32c_intel sysfillrect sysimgblt fb_sys_fops igb ttm ptp drm ahci pps_core libahci dca i2c_algo_bit libat
megaraid_sas i2c_core fjes [最後にアンロードされたもの: ip_tables]
7月8日 10:47:42 cztest カーネル: CPU: 10 PID: 0 通信: swapper/10 汚染: GW ------------ 3.10.0-514.16.1.el7.x86_64 #1
7月8日 10:47:42 cztestカーネル: ハードウェア名: Dell Inc. PowerEdge R630/02C2CP、BIOS 2.3.4 2016年11月8日
7月8日 10:47:42 cztest カーネル: 00000000000000000 dd79fe633eacd853 ffff88103e743880 ffffffff81686ac3
7月8日 10:47:42 cztest カーネル: ffff88103e7438b8 ffffffff81085cb0 ffff8806d5c57800 ffff88010a4e6c80
7月8日 10:47:42 cztest カーネル: 0000000000000001 00000000f90e778c 00000000000000001 ffff88103e7438c8
7月8日 10:47:42 cztestカーネル: コールトレース:
7月8日 10:47:42 cztestカーネル: <IRQ> [<ffffffff81686ac3>] dump_stack+0x19/0x1b
7月8日 10:47:42 cztestカーネル: [<ffffffff81085cb0>] warn_slowpath_common+0x70/0xb0
7月8日 10:47:42 cztestカーネル: [<ffffffff81085dfa>] warn_slowpath_null+0x1a/0x20
7月8日 10:47:42 cztestカーネル: [<ffffffff815c3663>] tcp_mark_head_lost+0x113/0x290
7月8日 10:47:42 cztestカーネル: [<ffffffff815c3f47>] tcp_update_scoreboard+0x67/0x80
7月8日 10:47:42 cztestカーネル: [<ffffffff815c964d>] tcp_fastretrans_alert+0x6dd/0xb50
7月8日 10:47:42 cztestカーネル: [<ffffffff815ca49d>] tcp_ack+0x8dd/0x12e0
7月8日 10:47:42 cztestカーネル: [<ffffffff815cb3a8>] tcp_rcv_established+0x118/0x760
7月8日 10:47:42 cztestカーネル: [<ffffffff815d5f8a>] tcp_v4_do_rcv+0x10a/0x340
7月8日 10:47:42 cztestカーネル: [<ffffffff812a84c6>] ? security_sock_rcv_skb+0x16/0x20
7月8日 10:47:42 cztestカーネル: [<ffffffff815d76d9>] tcp_v4_rcv+0x799/0x9a0
7月8日 10:47:42 cztestカーネル: [<ffffffffa0140036>] ? iptable_filter_hook+0x36/​​0x80 [iptable_filter]
7月8日 10:47:42 cztestカーネル: [<ffffffff815b1094>] ip_local_deliver_finish+0xb4/0x1f0
7月8日 10:47:42 cztestカーネル: [<ffffffff815b1379>] ip_local_deliver+0x59/0xd0
7月8日 10:47:42 cztestカーネル: [<ffffffff815b0fe0>] ? ip_rcv_finish+0x350/0x350
7月8日 10:47:42 cztestカーネル: [<ffffffff815b0d1a>] ip_rcv_finish+0x8a/0x350
7月8日 10:47:42 cztestカーネル: [<ffffffff815b16a6>] ip_rcv+0x2b6/0x410
7月8日 10:47:42 cztestカーネル: [<ffffffff815700d2>] __netif_receive_skb_core+0x582/0x800
7月8日 10:47:42 cztestカーネル: [<ffffffff815dc694>] ? tcp4_gro_receive+0x134/0x1b0
7月8日 10:47:42 cztestカーネル: [<ffffffff811dc861>] ? __slab_free+0x81/0x2f0
7月8日 10:47:42 cztestカーネル: [<ffffffff81570368>] __netif_receive_skb+0x18/0x60
7月8日 10:47:42 cztestカーネル: [<ffffffff815703f0>] netif_receive_skb_internal+0x40/0xc0
7月8日 10:47:42 cztestカーネル: [<ffffffff81571578>] napi_gro_receive+0xd8/0x130
7月8日 10:47:42 cztestカーネル: [<ffffffffa018b237>] igb_clean_rx_irq+0x387/0x700 [igb]
7月8日 10:47:42 cztestカーネル: [<ffffffff8155e862>] ? skb_release_data+0xf2/0x140
7月8日 10:47:42 cztestカーネル: [<ffffffffa018b933>] igb_poll+0x383/0x770 [igb]
7月8日 10:47:42 cztestカーネル: [<ffffffff815d3120>] ? tcp_write_timer_handler+0x200/0x200
7月8日 10:47:42 cztestカーネル: [<ffffffff81570c00>] net_rx_action+0x170/0x380
7月8日 10:47:42 cztestカーネル: [<ffffffff8108f63f>] __do_softirq+0xef/0x280
7月8日 10:47:42 cztestカーネル: [<ffffffff81698c1c>] call_softirq+0x1c/0x30
7月8日 10:47:42 cztestカーネル: [<ffffffff8102d365>] do_softirq+0x65/0xa0
7月8日 10:47:42 cztestカーネル: [<ffffffff8108f9d5>] irq_exit+0x115/0x120
7月8日 10:47:42 cztestカーネル: [<ffffffff816997b8>] do_IRQ+0x58/0xf0
7月8日 10:47:42 cztestカーネル: [<ffffffff8168e86d>] common_interrupt+0x6d/0x6d
7月8日 10:47:42 cztestカーネル: <EOI> [<ffffffff81514a22>] ? cpuidle_enter_state+0x52/0xc0
7月8日 10:47:42 cztestカーネル: [<ffffffff81514b69>] cpuidle_idle_call+0xd9/0x210
7月8日 10:47:42 cztestカーネル: [<ffffffff810350ee>] arch_cpu_idle+0xe/0x30
7月8日 10:47:42 cztestカーネル: [<ffffffff810e82a5>] cpu_startup_entry+0x245/0x290
7月8日 10:47:42 cztestカーネル: [<ffffffff8104f07a>] start_secondary+0x1ba/0x230
7月8日 10:47:42 cztestカーネル: ---[ トレース終了 6bc65b0c591c1794 ]---

ホスト環境は次のとおりです。

システム | Dell Inc.; PowerEdge R620;
プラットフォーム | Linux
カーネル | Centos 3.10.0-514.16.1.el7.x86_64
合計メモリ | 64G

処理命令

スタック印刷プロセスは、xfs アラーム処理に似ています。一般的なプロセスは、カーネルが sack および fack 機能をオンにした後、ネットワーク伝送中に必要な高速再送信と選択的再送信が、tcp_input.c ファイルの tcp_mark_head_lost 関数によって処理されることです。主に、伝送中に失われたパケットの数をマークします。以下に示すように、システムによって報告されるカーネル スタック情報は、tcp_mark_head_lost 関数の tcp_verify_left_out 関数呼び出しによってトリガーされます。

// ソース/include/net/tcp.h 

#define tcp_verify_left_out(tp) WARN_ON(tcp_left_out(tp) > tp->packets_out)

静的インライン符号なし int tcp_left_out(const struct tcp_sock *tp)
{
  tp->sacked_out + tp->lost_out を返します。
}

// ソース/include/asm-generic/bug.h 

#define __WARN() warn_slowpath_null(__FILE__, __LINE__)

#ifndef 警告オン
#define WARN_ON(条件) ({\
    __警告(); \
})
#終了



// ソース/net/ipv4/tcp_input.c

/* キューの先頭を損失としてマークすることで、上記のイベント「A」での損失を検出します。
 * FACKまたは非SACK(Reno)送信者の場合、最初の「パケット」セグメント数
 * は失われたとみなされます。RFC3517 SACKの場合、セグメントが失われたとみなされるのは、
 * 少なくともtp->reordering SACKedシーケンスが上に存在します。「パケット」とは
 * この制限に達する前に通過する最大の SACK セグメント数。
 */
静的 void tcp_mark_head_lost(構造体 sock *sk, int パケット, int mark_head)
{
  構造体 tcp_sock *tp = tcp_sk(sk);
  ....
  tcp_verify_left_out(tp); // dump_stack をトリガーする
}

...
静的 void tcp_update_scoreboard(構造体 sock *sk, int fast_rexmit)
{
  構造体 tcp_sock *tp = tcp_sk(sk);

  tcp_is_reno(tp) の場合 {
    tcp_mark_head_lost(sk, 1, 1);
  } そうでない場合 (tcp_is_fack(tp)) {
    int 失われた = tp->fackets_out - tp->reordering;
    (損失 <= 0)の場合
      失われた = 1;
    tcp_mark_head_lost(sk, 失われた, 0);
  } それ以外 {
    int sacked_upto = tp->sacked_out - tp->reordering;
    (sacked_upto >= 0)の場合
      tcp_mark_head_lost(sk, sacked_upto, 0);
    そうでない場合 (fast_rexmit)
      tcp_mark_head_lost(sk, 1, 1);
  }
}

redhat-536483 の説明によると、このエラー メッセージは通常、TCP バグによって発生し、カーネルが解放された TCP ソケット バッファー リストを使用するときにトリガーされる可能性があります。

根本的な原因
TCP カーネル ソケット バッファ リンク リストに関連する、解放後使用の問題です。したがって、これは TCP カーネル コードのバグです。このバグは TCP カーネル コードにありますが、複数の方法でトリガーされる可能性があります。NFS が原因でトリガーされる場合もありますし、アプリケーション (Java プロセスなど) が原因でトリガーされる場合もあります。

処理

カーネルのアップグレード

以下に示すように、RedHat はバージョン 3.10.0-520 で tcp_* 関連関数の解放後使用バグを修正した可能性があります。この問題を解決するには、アップグレードを試みることができます。
Centos 7.x の変更履歴

* 2016 年 11 月 3 日 (木) Rafael Aquini <[email protected]> [3.10.0-520.el7]
- [net] tcp: tcp_xmit_retransmit_queue() の解放後使用を修正 (Mateusz Guzik) [1379531] {CVE-2016-6828}

ファック/サック機能を無効にする

Red Hat ナレッジベースのドキュメントによると、tcp_mark_head_lost 関数は主に高速再送信と選択確認中に失われたパケットの数をマークするために使用されるため、この問題を回避するために fack/sack パラメータを一時的に無効にできる可能性があります。

sysctl -w net.ipv4.tcp_fack=0
sysctl -w net.ipv4.tcp_sack=0

まず 2 番目の方法を試してみて、問題が解決しない場合はカーネル バージョンのアップグレードを検討してください。

参照する

レッドハット-536483

バグ 1367091

CVE-2016-6828

カーネルコミット

要約する

以上がこの記事の全内容です。この記事の内容が皆様の勉強や仕事に何らかの参考学習価値をもたらすことを願います。123WORDPRESS.COM をご愛顧いただき、誠にありがとうございます。

以下もご興味があるかもしれません:
  • Linux システムによって報告される xfs_vm_releasepage 警告問題に対処する方法

<<:  MySQL グリーン解凍バージョンのインストールと設定手順

>>:  Vue での mixin の応用について議論する

推薦する

Linux での Python のアップグレードと pip のインストールの詳細な説明

Linuxバージョンのアップグレード: 1. まず、Linuxオペレーティングシステムに付属するPy...

Amoeba を使用して MySQL データベースの読み取り/書き込み分離を実装する方法の詳細な説明

MySQL には読み取りと書き込みを分離するアーキテクチャが多数あります。Baidu のそれらのほと...

Docker で Spring-boot プロジェクトをデプロイするためのサンプル コード

1. 基本的な Spring-boot クイックスタート1.1 クイックスタート pom.xml は...

Windows 10 での MySQL 5.7.21 インストーラのインストール グラフィック チュートリアル

MySQLをインストールしてメモしておきます。うまくインストールできるか分かりませんが、試してみます...

ネイティブ JavaScript を使用した Web 計算機の実装

この記事では、参考までに、計算機のWebバージョンを実装するためのJavaScriptの具体的なコー...

CentOS 8 に htop をインストールする方法のチュートリアル

システムをインタラクティブに監視したい場合は、htop コマンドが最適な選択肢の 1 つです。 ht...

JVMシリーズのメモリモデルの詳細な説明

目次1. メモリモデルとランタイムデータ領域2. マインドマップと凡例3. オブジェクトはJVMから...

Mapper SQL ステートメント フィールドとエンティティ クラス属性名の関係は何ですか?

背景: 1. データベースに通知テーブルがある あなたは見ることができますgmt_create、通知...

純粋な CSS ドロップダウン メニュー

成果を達成する実装コードhtml <div id="コンテナ"> &...

js 学習ノート: class、super、extends キーワード

目次序文1. es6の前にオブジェクトを作成する2. es6 後のクラス宣言3. クラスの継承4. ...

フロントエンド Vue ユニットテストを始める

目次1. ユニットテストはなぜ必要なのでしょうか? 2. ユニットテストの書き方3. テストツール4...

20個のJavaScriptワンラインコードを共有する

目次1. ブラウザのクッキーの値を取得する2. RGBを16進数に変換する3. クリップボードにコピ...

HTML チュートリアル: よく使われる HTML タグのコレクション (6)

関連記事:初心者が学ぶ HTML タグ (5)導入された HTML タグは、必ずしも XHTML 仕...

mysqlのkey_lenの計算方法についての簡単な説明

MySQL の explain コマンドは SQL のパフォーマンスを分析できます。その 1 つが ...