差分解析その1
カテゴリ”カーネル勉強”の初回の投稿なので、簡単な説明をします。
ミラクル社内で、定期的にカーネル勉強会を行っています。
現在は、毎週金曜日にRHEL4U2->U3に加わったパッチの解析
を行っています。
(なので、毎週金曜日には、ここのblogに投稿があるはず。)
本日は自分が担当でした。
解析パッチは、下のです。
linux-2.6.9-CVE-2005-3858-ip6-input-finish-dos.patch
まず、パッチの中身を見てみます。
=============================================================
--- linux-2.6.9.orig/net/ipv6/ip6_input.c 2004-10-18 23:54:40.000000000 +0
200
+++ linux-2.6.9/net/ipv6/ip6_input.c 2005-12-18 10:32:35.000000000 +0100
@@ -198,12 +198,13 @@
if (!raw_sk) {
if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
IP6_INC_STATS_BH(IPSTATS_MIB_INUNKNOWNPROTOS);
- icmpv6_param_prob(skb, ICMPV6_UNK_NEXTHDR, nhoff);
+ icmpv6_send(skb, ICMPV6_PARAMPROB,
+ ICMPV6_UNK_NEXTHDR, nhoff,
+ skb->dev);
}
- } else {
+ } else
IP6_INC_STATS_BH(IPSTATS_MIB_INDELIVERS);
- kfree_skb(skb);
- }
+ kfree_skb(skb);
}
rcu_read_unlock();
return 0;
=============================================================
大雑把にいうと、下記が変更内容
icmpv6_param_prob関数 -> icmpv6_send関数に変更
elseの外にkfree_skb(skb)関数 移動
目をしっかり開いてみると
if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
のelseのときにskbの解放処理がない。。。
if文の中はicmpv6_param_prob関数内で解放。なるほど。
109 /*
110 * Slightly more convenient version of icmpv6_send.
111 */
112 void icmpv6_param_prob(struct sk_buff *skb, int code, int pos)
113 {
114 icmpv6_send(skb, ICMPV6_PARAMPROB, code, pos, skb->dev);
115 kfree_skb(skb);
116 }
ここで簡単にまとめると、
linux-2.6.9-CVE-2005-3858-ip6-input-finish-dos.patch は
バッファ解放漏れ対処パッチ
ってかな。
ちょっと横道にそれて、一回の解放洩れがどのくらいかぁ?!調査。
やりかたは簡単
1 debuginfoが入っているマシンにログイン。
2 crashコマンド実施。
3 crash> struct sk_buff
結果
crash> struct sk_buff
struct sk_buff {
:
}
SIZE: 176
おぉぉ。
次に、どんなときに解放漏れルートに入るのか調査。
xfrm6_policy_check がポイント
この関数が0を返すときにバッファ解放洩れが発生。
ルートを追ってみる。
xfrm6_policy_check(include/net/xfrm.h)
+-> xfrm_policy_check(xfrm_policy_check)
+ -> __xfrm_policy_check(net/xfrm/xfrm_policy.c)
__xfrm_policy_checkのリターン値がそのまま、返却されている。
ってことで、__xfrm_policy_checkの関数が0を返すところを調査。
net/xfrm/xfrm_policy.c
912 int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
913 unsigned short family)
914 {
915 struct xfrm_policy *pol;
916 struct flowi fl;
917
918 if (_decode_session(skb, &fl, family) < 0)
919 return 0;
920
: :
927 if (!xfrm_selector_match(&xvec->xvec->sel, &fl, family))
928 return 0;
: :
発見。おぉ見ていくと結構あるなぁ。。
ここでグーグルしてちょっと検索。
xfrm_policy_checkが何をやっているのか検索。
難しい。。。
って検索しているうちに本問題の報告を発見。
http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2005-3858
ここに
Memory leak in the ip6_input_finish function in ip6_input.c in Linux kernel 2.6.12
and earlier might allow attackers to cause a denial of service via malformed IPv6 packets with unspecified parameter problems, which prevents the
SKB from being freed.
情報集まったので、パッチ差分解析結果です。
=======================================================
1. 該当パッチ
linux-2.6.9-CVE-2005-3858-ip6-input-finish-dos.patch
2. 現象
メモリリークのため、システムのサービスに影響を及ぼす。
3. 発生条件
IPv6のDos攻撃を受けた時。
4. 修正情報
(1)修正前
解放処理がなし。
(2)修正後
解放処理があり。
5. 影響度調査
本件はセキュリティレベルの問題のため、影響度が高い
と考えられる。
=======================================================



最近のコメント