トラックバックでBus Error (10)

久しぶりのサーバやサイトの管理をしてみました。Webサーバのバージョンをあげてみたりとか、リンク切れを修正してみたりとか、見た目的には何も変わらないので非常に報われない作業です。そんな中でWebサーバのエラーログを見たのですが、あまり見たくないエラーがありました。ありえない領域をアクセスした際に発生するBus Errorというエラーが。
そういえばここ1年くらいトラックバックがないなぁと思って調べてみると、どうやらトラックバックが送られてきたときにこのエラーが発生しているようです。

このサイトにもしトラックバックを送られていた方がいたら本当にごめんなさい。現在鋭意作業中ですが、また解決には至っていません。以下、その闘いの記録です。

※その後、strstr()の問題とわかり、mod_encodingのソースを修正することで解決しました。

症状
トラックバックが送られてくるとバスエラーでWebサーバのプロセスが落ちる。
エラーログを見ると

[Mon Jul 24 00:11:01 2006] [notice] child pid 9611 exit signal Bus error (10)

状況
現在このサイトはMacOSX(10.2.8 darwin 6.8)上でapache-1.3.36 + mod_perl-1.29 + libapreq-1.3等を使用し、CMSとしてMovableType 2.661で運営。MovableTypeはmod_perl上で動作中。
Apacheは

Apache/1.3.36 (Darwin) DAV/1.0.3 mod_ruby/1.2.6 mod_perl/1.29 mod_ssl/2.8.27 OpenSSL/0.9.7d configured -- resuming normal operations

perlは

$ perl -V
Summary of my perl5 (revision 5.0 version 8 subversion 0) configuration:
Platform:
osname=darwin, osvers=6.6, archname=darwin
uname='darwin macintosh.local. 6.6 darwin kernel version 6.6: thu may 1 21:48:54 pdt 2003; root:xnuxnu-344.34.obj~1release_ppc power macintosh powerpc '
config_args='-de -Dprefix=/usr'
hint=recommended, useposix=true, d_sigaction=define
usethreads=undef use5005threads=undef useithreads=undef usemultiplicity=undef
useperlio=define d_sfio=undef uselargefiles=define usesocks=undef
use64bitint=undef use64bitall=undef uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-pipe -fno-common -no-cpp-precomp -fno-strict-aliasing -I/usr/local/include',
optimize='-O3',
cppflags='-no-cpp-precomp -pipe -fno-common -no-cpp-precomp -fno-strict-aliasing -I/usr/local/include'
ccversion='', gccversion='3.1 20020420 (prerelease)', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=8
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=8, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -flat_namespace -L/usr/local/lib'
libpth=/usr/local/lib /usr/lib
libs=-lm -lc
perllibs=-lm -lc
libc=/usr/lib/libc.dylib, so=dylib, useshrplib=true, libperl=libperl.dylib
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_dyld.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
cccdlflags=' ', lddlflags=' -flat_namespace -bundle -undefined suppress -L/usr/local/lib'

Characteristics of this binary (from libperl):
Compile-time options: USE_LARGE_FILES
Built under darwin
Compiled at Sep 20 2003 02:17:35
@INC:
/System/Library/Perl/darwin
/System/Library/Perl
/Library/Perl/darwin
/Library/Perl
/Library/Perl
/Network/Library/Perl/darwin
/Network/Library/Perl
/Network/Library/Perl
.

症状の分析

  • mt-tb.cgiをPOSTメソッドで叩くと落ちる
  • GETメソッドで叩くviewコマンド(以前のトラックバック情報を得る)やrssコマンド(RSSでトラックバック情報を取得)は落ちない
  • トラックバックを送るのにmt-tb.cgiをGETで叩くと成功する。例えば
    mt_tb.cgi/(Trackback ID)?__mode=ping&title=hoge&url=hoge&excerpt=hoge&blog_name=hoge
    は成功する
  • mod_perlを切ると問題なく動作

作業状況

  • libapreqを最新バージョン(1.33)にあげてみようとするもmake testでコアを吐いてとまってしまうので断念(Apache::Test-1.28が悪い?)
  • libapreq-1.3のCソース(c/apache_request.c)にデバックコードを挿入してみるも、デバックコードに到達する以前にBus Errorで落ちてしまっている
  • libapreqのperl拡張の部分を現在調査中だがperlの拡張モジュールを読み書きした経験がないので困惑中
  • 最新のperl-5.8.8にバージョンをあげることを考えるが、現行のバックアップ等を足ってからにしたいので未完
  • Googleで調査してみるも同症状には出くわしていない

その後、コアファイル(/Library/Logs/CrashReporter/httpd.crash.log)を入手

Date/Time: 2006-07-24 00:11:00 +0900
OS Version: 10.2.8 (Build 6R73)
Host: Macintosh.local.

Command: httpd
PID: 9611

Exception: EXC_BAD_ACCESS (0x0001)
Codes: KERN_PROTECTION_FAILURE (0x0002) at 0x00000000

Thread 0 Crashed:
#0 0x900158d4 in strstr
#1 0x004843e0 in mod_enc_convert
#2 0x00098c8c in run_method
#3 0x00098f4c in ap_run_post_read_request
#4 0x000a2bd8 in ap_read_request
#5 0x0007d82c in child_main
#6 0x0007db80 in make_child
#7 0x0007e07c in perform_idle_server_maintenance
#8 0x0007e91c in standalone_main
#9 0x0007f1f0 in main
#10 0x000026a0 in _start
#11 0x00002520 in start

PPC Thread State:
srr0: 0x900158d4 srr1: 0x0000f030 vrsave: 0x00000000
xer: 0x00000000 lr: 0x900158d0 ctr: 0x90000e40 mq: 0x00000000
r0: 0x900158d0 r1: 0xbffff680 r2: 0x312e3100 r3: 0x00000007
r4: 0x80808080 r5: 0x00000000 r6: 0x80808080 r7: 0x00000000
r8: 0x00000000 r9: 0x00486a55 r10: 0x900e161c r11: 0xa0004318
r12: 0x90000e40 r13: 0x00000000 r14: 0x00000000 r15: 0x00000000
r16: 0x00000000 r17: 0x00000000 r18: 0x00000000 r19: 0x00000000
r20: 0x00000000 r21: 0x00000000 r22: 0x00000000 r23: 0x00000000
r24: 0x00000000 r25: 0x00000000 r26: 0xbffffddc r27: 0x00000007
r28: 0x00000057 r29: 0x00486a55 r30: 0x00000000 r31: 0x00484308

思惑が完全に外れていたようです。mod_davを導入するためにmod_encodingを入れていたのですが、その中のstrstr()関数で落ちているようです。見てみたところ、NULLチェックができていないのが原因のようでした。

mod_encoding.cの484行目付近

int hfsClient = 0;
const char *userAgent = ap_table_get(r->headers_in, "User-Agent");
if (strstr(userAgent, "WebDAVFS")) {
    hfsClient = 1;
}

を以下のように修正

int hfsClient = 0;
const char *userAgent = ap_table_get(r->headers_in, "User-Agent");
if (userAgent && strstr(userAgent, "WebDAVFS")) {
    hfsClient = 1;
}

July 24, 2006 00:10 fenrir が投稿 : 固定リンク | | このエントリーを含むはてなブックマーク

コメント

コメントする