Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: linux-gnu Compiler: /bind/obj/repos/dist-buildroot.hg/build_x86_64/staging_dir/usr/bin/x86_64-linux-uclibc-gcc Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPA uname output: Linux bogga 2.6.18.8-x86_64-xen0 #39 Wed Oct 3 11:13:22 BST 2007 x86_64 GNU/Linux Machine Type: x86_64-pc-linux-gnu
Bash Version: 3.2 Patch Level: 17 Release Status: release Description: I am cross compiling bash 3.2 in a uclibc environment using buildroot, the target is x86_64. Because of the cross compilation the configure test for "if getcwd() will dynamically allocate memory" fails and so the version in lib/sh/getcwd.c is used. The code to handle buf == NULL in this version of getcwd() is buggy where it sets len = size at line 256: size_t len = pathbuf + pathsize - pathp; if (buf == NULL) { if (len < (size_t) size) len = size; ... (void) memcpy((PTR_T) buf, (PTR_T) pathp, len); ... If size is greater than "pathbuf + pathsize - pathp" then the memcpy at line 267 will copy past the end of the path[] buffer. Depending on the stack layout / depth etc this can result in a segmentation fault as memcpy copies past the top of the stack. Repeat-By: It's a bit tricky but I see it by repeatedly running: chroot /uclibc-root /bin/bash in a Xen domain0 (kernel with some bits from rhel5x). There is some randomisation of the stack in this configuration (exec-shield I think) which means the segfault does not occur every time. Fix: The fix is really to pre-seed config.cache so that it knows that the uclibc version of getcwd() does the right thing but the fix for the problem in lib/sh/getcwd.c is the patch below from my colleague Christian Limpach. Index: bash-3.2/lib/sh/getcwd.c =================================================================== --- bash-3.2.orig/lib/sh/getcwd.c 2007-10-09 09:53:38.000000000 +0100 +++ bash-3.2/lib/sh/getcwd.c 2007-10-09 09:53:54.000000000 +0100 @@ -251,19 +251,21 @@ { size_t len = pathbuf + pathsize - pathp; - if (buf == NULL) + if (buf == NULL && size < 0) { - if (len < (size_t) size) - len = size; - buf = (char *) malloc (len); - if (buf == NULL) - goto lose2; + size = len; } - else if ((size_t) size < len) + if ((size_t) size < len) { errno = ERANGE; goto lose2; } + if (buf == NULL) + { + buf = (char *) malloc (size); + if (buf == NULL) + goto lose2; + } (void) memcpy((PTR_T) buf, (PTR_T) pathp, len); }