[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Bug in getcwd implementation in lib/sh/getcwd.c

From: Ian Campbell
Subject: Bug in getcwd implementation in lib/sh/getcwd.c
Date: Tue, 09 Oct 2007 14:48:53 +0100

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
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 #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


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.


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.


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);

reply via email to

[Prev in Thread] Current Thread [Next in Thread]