This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug other/61895] New: libbacktrace crashes with bus error with empty file argv[0]


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61895

            Bug ID: 61895
           Summary: libbacktrace crashes with bus error with empty file
                    argv[0]
           Product: gcc
           Version: 4.10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: other
          Assignee: unassigned at gcc dot gnu.org
          Reporter: vogt at linux dot vnet.ibm.com

Docker uses a call of the exec family to start a new process with a bogus
argv[0] argument, i.e. argv[0] points to an empty file, not a real executable. 
libbacktrace opens the empty file, mmaps it and uses it without ever checking
the size of the file.  Eventually, libbacktrace causes a bus error (on s390x,
may be a different fault on other architectures) in elf.c:564:

  memcpy (&ehdr, ehdr_view.data, sizeof ehdr);

-----

The problem can be reproduced like this (it's probably possible to reproduce
this with a C program):

-- BEGIN exec.c --
#include <unistd.h>

int main(int argc, char *argv[])
{
    execv(argv[0], &argv[1]);
    return 1;       
}
-- END exec.c --

-- BEGIN hello.go --
package main
import "fmt"

func main() {
    fmt.Println("Hello!")
}
-- END hello.go --

$ gcc -o exec exec.c
$ gccgo -g -o hello hello.go
$ touch empty
$ ./exec ./hello $PWD/empty
Bus error (core dumped)

-----

Fix: libbacktrace needs to sanitize its input, i.e. the files it tries to open
in fileline_initialize().  Such a file must be at least as long as sizeof ehdr,
but there may be more places in the code that don't do size checking.  The
right approach might be something like this:

  descriptor = backtrace_open(...)
  if (descriptor >= 0)
    {
      if (!is_executable_valid(descriptor))
        {
          /* close descriptor */
          /* maybe emit an error message */
          /* try other files */
        }
    }

  int is_executable_valid(int descriptor)
  {
    ...
  }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]