libsmbclient + nss_wins の問題 (3)

謎は解けた。

と謎を追ってきたのですが,非 static な関数があたかも static 定義な関数のように振る舞っていたのは,リンカのフラグに -Bsymbolic-functions が指定されていた(on Ubuntu Hardy 8.04)ためでした。-Bsymbolic-functions については ld 2.18 の -Bsymbolic オプションを使うと共有ライブラリ内でシンボルをローカルバインドできる - daily dayflower を参照してください。

一応背景

Samba の lib/debug.c のコードの抜粋を再掲します。

/* source/lib/debug.c: */

/******* snip snip snip *******/

static int debug_all_class_hack = 1;

int     *DEBUGLEVEL_CLASS = &debug_all_class_hack;

/******* snip snip snip *******/

int debug_add_class(const char *classname)
{
    void *new_ptr;

    /******* snip snip snip *******/

    new_ptr = DEBUGLEVEL_CLASS;
    if (DEBUGLEVEL_CLASS == &debug_all_class_hack) {
            /* Initial loading... */
            new_ptr = NULL;
    }
    new_ptr = SMB_REALLOC_ARRAY(new_ptr, int, debug_num_classes + 1);
    if (!new_ptr)
            return -1;
    DEBUGLEVEL_CLASS = (int *)new_ptr;

    /******* snip snip snip *******/
}

DEBUGLEVEL_CLASSdebug_add_class() も非 static なシンボルです。

今回の状況は,libsmbclient.so と libnss_wins.so で各々このソースが読み込まれていることにあります。これまでは両者とも非 static なので,共有ライブラリが読み込まれたときにごっそりといれかわっていました。

つまり(単純にいうと)-lsmbclient -lnss_wins でビルドすると,両シンボルともに libsmbclient.so 由来のものになっていました。これなら問題ありません。

しかし,-Bsymbolic-functions というオプションつきでビルドすると,libnss_wins.so 内から debug_add_class() を呼び出した場合,libnss_wins.so 内の debug_add_class() が呼び出されることになります。すると,変数 DEBUGLEVEL_CLASS は libsmbclient.so 由来ですが static 変数の debug_all_class_hack は libnss_wins.so 由来になってしまうので,実は初期化されていないのに,初期化済みとみなされ,不正な realloc() をしてしまうのです。

まるでわからない説明だと思いますが,詳しくお知りになりたい方は上記にあげた3つの記事を読んでみてください。

なんで Samba が -Bsymbolic-functions つきでビルドされたか

それは krb5-dev の krb5-config --libs を実行すると -Wl,-Bsymbolic-functions が出力されるからです。

なんで krb5-configLDFLAGS-Wl,-Bsymbolic-functions になっているのか

それは dpkg-buildpackageLDFLAGS のデフォルトが -Wl,-Bsymbolic-functions だからです。

ということで

どうみても Ubuntu Hardydpkg のバグです。ありがとうございます。

ちなみに Upstream な Debiandpkg では,Ubuntu のを参考にして LDFLAGS のデフォルトを設定したあとにやっぱそれまずいわと取り下げてます。やれやれ。


いちおう dpkg@Ubuntu の launchpad に報告をあげておきましたが,どうなることやら。