(toppers-users 4736) Re: TINET 1.7のNULLポインタアクセスについて

H.Hata hgarb @ lowl.eek.jp
2018年 1月 20日 (土) 23:34:07 JST


阿部先生

お世話になっております。 畑です。
対応ありがとうございます。

 先ほどのメールではNUM_IN4_STATIC_ROUTE_ENTRY、NUM_IN4_ROUTE_ENTRY
に問題があると記載しましたが、実際は別の原因だったようです。
間違った推測でお手数をおかけしてしまい申し訳ありませんでした。

以下にgccの-save-tempsオプションで取得したプリプロセッサ出力を記載します。

--------------------------
2202:  T_IN4_RTENTRY *srt = 
2203 : # 151 "../../toppers_rx/asp/tinet/netinet/in4_subr.c" 3 4
2204 :                       ((void *)0)
2205 : # 151 "../../toppers_rx/asp/tinet/netinet/in4_subr.c"
2206 :                          ;
2207 :   int_t diff, sdiff = 0x7fffffff;
2208 : 
2209 :   (wai_sem(14));
2210 :   for (ix = 3; ix < (3 + 1); ix ++) {
2211 :    rt = &_tinet_routing4_tbl[ix];
2212 :    diff = (int_t)(rt->expire - now);
2213 :    if (diff <= 0) {
2214 : 
2215 :     frt = rt;
2216 :     break;
2217 :     }
2218 :    else if (diff < sdiff) {
2219 :     srt = rt;
2220 :     sdiff = diff;
2221 :     }
2222 :    }
2223 :   if (frt == 
2224 : # 168 "../../toppers_rx/asp/tinet/netinet/in4_subr.c" 3 4
2225 :             ((void *)0)
2226 : # 168 "../../toppers_rx/asp/tinet/netinet/in4_subr.c"
2227 :                 )
2228 :    frt = srt;
2229 :   frt->flags = 0;
2230 :   (sig_sem(14));
2231 :   }
-----------------------------
NUM_IN4_STATIC_ROUTE_ENTRY、NUM_IN4_ROUTE_ENTRYの条件は2210行なので
for文の中身は実行されているようです。

  アセンブラを詳しく見るとNULLポインタアクセスの前に変数が0x7fffffffと
一致した場合のみNULLポインタアクセスが実行されるコードが生成されています。

> > 08002279 <.LM18>:
> >   8002279: 74 0e ff ff ff 7f  cmp #0x7fffffff, r14
> >   800227f: 21 2d              bne.b 80022ac <.LM29>
> > 
> > 08002281 <.LM19>:
> >   8002281: 66 07              mov.l #0, r7
> >   8002283: 84 77              mov.b r7, 16[r7]  ; NULL ポインタアクセス
> >   8002285: 05 92 dd ff        bsr.a 8000017 <_abort> ; abort挿入


上記を踏まえてコードを見ると2213行目と2218行目の条件式でdiffが0以下と
0x7fffffff未満の条件は記載されていますが、一致する条件が漏れています。
gccはこれを検出して一致条件でのNULLポインタアクセスを生成したようです。

お忙しいとは思いますが、コード修正の検討をお願いします。


On Thu, 18 Jan 2018 16:37:26 +0900
ABE Tsukasa <abe @ tomakomai-ct.ac.jp> wrote:

> 畑様
> 
> 苫小牧高専の阿部です。
> 
> 
> > 
> > 阿部先生
> > 
> > お世話になっております。畑 尚志と申します。
> > TINETの設定で質問があります。
> > 
> > 質問について:
> >  ASP用 TINET 1.7でechos4のサンプルをデフォルト設定でコンパイルすると
> > NULLポインタアクセスが検出されます。
> > 該当箇所を調べたところ tinet/netinet/in4_subr.cのin_rtnewentry関数
> > で発生しているようです。
> > 
> > tinet/netinet/in4_subr.c
> > 
> > 129 : T_IN4_RTENTRY *
> > 130 : in_rtnewentry (uint8_t flags, uint32_t tmo)
> > 131 : {
> > 132 :   SYSTIM  now;
> > 133 :   T_IN4_RTENTRY   *rt, *frt = NULL;
> >           .
> >           . (省略)
> >           .
> > 150 :/* 空きがなければ、有効時間がもっとも短いエントリを空きにする。*/
> > 151 :   T_IN4_RTENTRY	*srt = NULL;
> > 152 :   int_t		diff, sdiff = INT_MAX;
> > 153 :
> > 154 :   syscall(wai_sem(SEM_IN4_ROUTING_TBL));
> > 155 :   for (ix = NUM_IN4_STATIC_ROUTE_ENTRY; ix < NUM_IN4_ROUTE_ENTRY; ix ++) {
> > 156 :       rt = &routing4_tbl[ix];
> > 157 :       diff = (int_t)(rt->expire - now);
> > 158 :       if (diff <= 0) {	/* rt->expire <= now */
> > 159 :                       /* 既に、有効時間が過ぎている。*/
> > 160 :                       frt = rt;
> > 161 :                       break;
> > 162 :                      }
> > 163 :       else if (diff < sdiff) {
> > 164 :            srt = rt;
> > 165 :            sdiff = diff;
> > 166 :       }
> > 167 :   }
> > 168 :   if (frt == NULL)
> > 169 :       frt = srt;
> > 170 :   frt->flags = 0;
> > 171 :   syscall(sig_sem(SEM_IN4_ROUTING_TBL));
> > 172 :   }
> > 173 :
> > 174 : frt->flags  = (uint8_t)(flags | IN_RTF_DEFINED);
> > 175 : frt->expire = now + tmo / SYSTIM_HZ;
> > 176 : return frt;
> > 
> >  echos4の初期設定でコンパイルした場合155行目のfor文の条件が常に成立しない
> > ため最適化で削除され、170行目のfrt->flagsがNULLポインタアクセスになるよう
> > です。
> >  NUM_IN4_STATIC_ROUTE_ENTRY、NUM_IN4_ROUTE_ENTRYに関する設定に問題があり
> > そうなのですが必要な設定等あるでしょうか?
> > 
> 
> tinet/netinet/in4_subr.c の 109行
> 
> --
> #if NUM_IN4_REDIRECT_ROUTE_ENTRY > 0
> --
> 
> と、tinet/tinet_config.h の 113行からの定義で、
> 
> --
> /* ルーティング表のエントリ数の定義 */
> 
> #define NUM_IN6_ROUTE_ENTRY			\
> 	(NUM_IN6_STATIC_ROUTE_ENTRY + NUM_IN6_REDIRECT_ROUTE_ENTRY)
> 					/* ルーティング表のエントリ数	*/
> 
> #define NUM_IN4_ROUTE_ENTRY		\
> 	(NUM_IN4_STATIC_ROUTE_ENTRY + NUM_IN4_REDIRECT_ROUTE_ENTRY)
> --
> 
> から、
> 
> NUM_IN4_STATIC_ROUTE_ENTRY < NUM_IN4_ROUTE_ENTRY
> 
> の条件が成立しているはずなので、for文の条件も成立すると思いますが、
> そうはなっていないようですね。
> こちらで調べてみます。
> いずれにしても、
> 
>  > 168 :   if (frt == NULL)
>  > 169 :       frt = srt;
>  > 170 :   frt->flags = 0;
> 
> は問題がありそうです。
> 修正を検討します。
> 
> > 
> > 質問の背景:
> >    rx-elf-gcc 7.2.0+newlibの環境でTINET1.7をコンパイルするとkill、_exit等の
> > OS依存の関数がリンクされエラー終了します。
> >  調査のため実行ファイルを逆アセンブルすると、NULLポインタアクセスのあとに
> > ソースコードに無いabortが挿入されている事がわかりました。どうも最近のgccは
> > NULLポインタアクセスを検出するとabortを挿入するようです。
> >  OS依存の関数がリンクされるとnewlib_stubが必要になるためabortの除去を行い
> > たいです。
> > 
> > 08002247 <__tinet_in_rtnewentry>:
> >     .
> >     .
> >     .
> > 08002279 <.LM18>:
> >   8002279: 74 0e ff ff ff 7f  cmp #0x7fffffff, r14
> >   800227f: 21 2d              bne.b 80022ac <.LM29>
> > 
> > 08002281 <.LM19>:
> >   8002281: 66 07              mov.l #0, r7
> >   8002283: 84 77              mov.b r7, 16[r7]  ; NULL ポインタアクセス
> >   8002285: 05 92 dd ff        bsr.a 8000017 <_abort> ; abort挿入
> > 
> > 以上、よろしくお願いします。
> > 
> 
> 私の開発環境は、主に CS+ に移行しており、
> GCC の環境も古いままのため、検出できませんでした。
> GCC の開発環境の更新も検討します。
> 
> よろしくお願いします。
> 
> -- 
> .\" 苫小牧工業高等専門学校 創造工学科 情報科学・工学系
> .\" 教授 阿部 司
> .\" 〒059-1275 北海道苫小牧市字錦岡443番地
> .\" E-mail: abe @ tomakomai-ct.ac.jp  TEL/FAX: 0144-67-8937


-- 
H.Hata <hgarb @ lowl.eek.jp>