2009年2月5日木曜日

(FreeBSD) sambaのconfigureで、checking if the realpath function allows a NULL argument... ~固まった

微妙に古いFreeBSD 6.3-STABLEなマシンで、ports/japanese/samba3をmakeしたときのことなんですが、configureの途中で、



checking for working mmap... (cached) yes
checking for fcntl locking... yes
checking for broken (glibc2.1/x86) 64 bit fcntl locking... no
checking for 64 bit fcntl locking... no
checking for st_blocks in struct stat... yes
checking for st_blksize in struct stat... yes
checking for st_flags in struct stat... yes
checking for broken nisplus include files... no
checking if the realpath function allows a NULL argument...



と、ここまで表示されて、まったく先に進まなくなります。



topで見てみると



  PID USERNAME         THR PRI NICE   SIZE    RES STATE    TIME   WCPU COMMAND
68040 root               1 127    0  2408K   744K RUN      1:43 92.58% conftest



という感じで、configureから実行されるチェックプログラムのconftestが暴走してるみたいです。



gdbで見てみると



# gdb ./conftest 68040
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-marcel-freebsd"...(no debugging symbols found)...
Attaching to program: /ports.work/ports/japanese/samba3/work/samba-3.0.34/source/conftest, process 68040
Reading symbols from /usr/local/lib/libexecinfo.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/local/lib/libexecinfo.so.1
Reading symbols from /usr/local/lib/libiconv.so.3...(no debugging symbols found)...done.
Loaded symbols for /usr/local/lib/libiconv.so.3
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/libm.so.4...(no debugging symbols found)...done.
Loaded symbols for /lib/libm.so.4
Reading symbols from /libexec/ld-elf.so.1...(no debugging symbols found)...done.
Loaded symbols for /libexec/ld-elf.so.1
0x481a57a7 in realpath () from /lib/libc.so.6
(gdb)
(gdb) where
#0  0x481a57a7 in realpath () from /lib/libc.so.6
#1  0x08048578 in main ()



デバッグシンボルのないライブラリをリンクしているので、詳細は不明ですが、とりあえず、realpathの中で暴走してるみたいです。



conftestはどんなプログラムなのか見てみると



・・・略・・・
#define HAVE_STAT_ST_BLOCKS 1
#define HAVE_STAT_ST_BLKSIZE 1
#define HAVE_STAT_ST_FLAGS 1
/* end confdefs.h.  */



#include <stdio.h>
#include <limits.h>
main() {
        char *newpath = realpath("/tmp", NULL);
        exit ((newpath != NULL) ? 0 : 1);
}



なんていうコードです。realpathのマニュアルを読むと、realpathの第2引数には、ちゃんとメモリを確保して渡してやらないといけない、と書いてあるのに、あえてNULLを指定して、動くかどうか試してる・・・



sambaよ、あんた、いったい何をやりたいんですか?



ついでだから、realpathのソースコードをのぞいてみましょ。



# locate realpath.c
/usr/compat/linux/usr/share/doc/bash-3.0/loadables/realpath.c
/usr/src/bin/realpath/realpath.c
/usr/src/contrib/binutils/libiberty/lrealpath.c
/usr/src/crypto/openssh/openbsd-compat/realpath.c
/usr/src/lib/libc/stdlib/realpath.c



たぶん、これでしょう。



# ls -l /usr/src/lib/libc/stdlib/realpath.c
-rw-r--r--  1 root  wheel  5758  5 28  2003 /usr/src/lib/libc/stdlib/realpath.c



# what /usr/src/lib/libc/stdlib/realpath.c
/usr/src/lib/libc/stdlib/realpath.c:
        realpath.c      8.1 (Berkeley) 2/16/94



whatじゃよくわかんない。中を見てみましょう。



#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)realpath.c  8.1 (Berkeley) 2/16/94";
#endif /* LIBC_SCCS and not lint */
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/lib/libc/stdlib/realpath.c,v 1.20 2003/05/28 08:23:01 fjoe Exp $");



revision 1.20ですね。



ソースコードは、こんな感じ。



char *
realpath(const char *path, char resolved[PATH_MAX])
{
    struct stat sb;
    char *p, *q, *s;
    size_t left_len, resolved_len;
    unsigned symlinks;
    int serrno, slen;
    char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];



    serrno = errno;
    symlinks = 0;
    if (path[0] == '/') {
        resolved[0] = '/';
        resolved[1] = '\0';



第2引数resolvedにNULLを指定すると、segmentation faultになりそうなんですが・・・なぜ暴走してるんでしょうか。それはそれで謎です。





とりあえずの解決方法としては、暴走してるconftestをkillしちゃう、というもの。



# kill 68040



ホント、とりあえずなんですが、これで、configureの処理が先に進みます。



configure:50431: checking if the realpath function allows a NULL argument
configure:50461: cc -o conftest -O2 -fno-strict-aliasing -pipe -DLDAP_DEPRECATED -D_SAMBA_BUILD_=3 -I/usr/local/include -I/usr/local/include -I/usr/local/include  -L/usr/local/lib -Wl,-R/usr/local/lib -L/usr/local/lib -L/usr/local/lib conftest.c -lexecinfo   -liconv >&5
conftest.c: In function `main':
conftest.c:418: warning: initialization makes pointer from integer without a cast
configure:50465: $? = 0
configure:50471: ./conftest
configure:50475: $? = 143
configure: program exited with status 143
configure: failed program was:





この現象は、7.1-STABLEなマシンでは発生していなくて、半年以上前の6.3-STABLEなマシンで発生しました。



6.3だから必ず起きる、というわけではないのかもしれません。



こんな変なcheckプログラムを流そうとする極悪ソフトウェアなんて、もうどうでもいいや、という気がしているので、あんまり調べる気にもなれません。



ちなみに、configure.inの、この部分ですね。



AC_CACHE_CHECK([if the realpath function allows a NULL argument],samba_cv_REALPATH_TAKES_NULL,[
AC_TRY_RUN([
#include <stdio.h>
#include <limits.h>
main() {
    char *newpath = realpath("/tmp", NULL);
    exit ((newpath != NULL) ? 0 : 1);
}
],
samba_cv_REALPATH_TAKES_NULL=yes,samba_cv_REALPATH_TAKES_NULL=no,samba_cv_REALPATH_TAKES_NULL=cross)])
if test x"$samba_cv_REALPATH_TAKES_NULL" = x"yes"; then
    AC_DEFINE(REALPATH_TAKES_NULL,1,[Whether the realpath function allows NULL])
fi


どうして、マニュアルに書いてあることを無視して、NULLを渡すという変なことをするんですか。そんな変なコードを書くのは、Linux方面の仕業に違いない(←偏見です!)・・・と思って、CentOSで、realpathのマニュアルを見てみました。


ERRORS
       EACCES Read or search permission was denied for a component of the path
              prefix.



       EINVAL Either  path or resolved_path is NULL. (In libc5 this would just
              cause a segfault.)  But, see NOTES below.



~~~略~~~



NOTES
       The glibc implementation of realpath() provides a  non-standard  exten-
       sion.  If resolved_path is specified as NULL, then realpath() uses mal-
       loc(3) to allocate a buffer  of  up  to  PATH_MAX  bytes  to  hold  the
       resolved  pathname,  and  returns a pointer to this buffer.  The caller
       should deallocate this buffer using free(3).


ビンゴ。なるほどね。



それにしても、どうして、sambaは、"non-standard extension"に期待しなくちゃならんのですか?すなおに、メモリを確保すりゃいいのに。



0 件のコメント:

コメントを投稿