RVM
  1. RVM
  2. RVM-1027

Crash when bootimage runner uses longjmp

    Details

    • Type: Bug Bug
    • Status: Open Open
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: 3.1.3
    • Fix Version/s: 1000
    • Labels:
      None
    • Environment:
      IA32 and PPC (confirmed for x86_64 and ppc32)
    • Number of attachments :
      0

      Description

      Reported by Carl Ritson on the researchers mailing list [1]:

      In bootImageRunner/sys.C, the function sysThreadTerminate() uses
      longjmp() to return from the VM stack to the thread stack at thread
      termination.

      In recent versions of glibc, longjmp() passes through a checking
      function __longjmp_chk() which attempts to ensure that the jump is to
      a valid stack frame. It does this by asserting that the new stack
      pointer is either greater than then current one, or contained on the
      alternate signal stack. As stacks grow downward (on x86 at least),
      this ensures that longjmp() only ever unwinds the stack. This
      assertion is obviously flawed when an separately allocated stack is
      used, such as in JikesRVM.

      On a modern Linux kernel mmap() allocates memory top-down, so
      successive allocations (tend to) fall on lower addresses. Thus in
      practice thread stacks are higher in memory than VM stacks, so the
      __longjmp_chk() assertion succeeds. However, a legacy mode of
      bottom-up allocation is also supported, this can be activated by
      setting the process personality (e.g. setarch -L) or having an
      unlimited stack size in the process resource limits (e.g. ulimit -s
      unlimited). The second of these is obscure, but it what resulted in
      my discovery of this issue.

      In bottom-up mode thread stacks are allocated below the VM memory area
      (at least on x86_64 32-bit mode), and hence __longjmp_chk fails.
      For JikesRVM in production configuration on x86_64-linux the error
      looks like the following (produced from DaCapo 2006 eclipse, on Ubuntu
      12.04 LTS):

      *** longjmp causes uninitialized stack frame ***:
      dist/gc/production/JikesRVM terminated
      ======= Backtrace: =========
      /lib32/libc.so.6(__fortify_fail+0x45)[0x557e0675]
      /lib32/libc.so.6(+0x1035ca)[0x557e05ca]
      /lib32/libc.so.6(__longjmp_chk+0x4b)[0x557e053b]
      dist/gc/production/JikesRVM(sysLongDivide+0x0)[0x804e68b]
      [0x64707099]
      

      There's also a bootloader crash that occurs on an unmodified PPC32 system which seems to have the same cause (no stacktrace is provided in that case).

      [1] http://sourceforge.net/mailarchive/message.php?msg_id=30708025

        Activity

        Hide
        Erik Brangs added a comment -

        Committed quick fiy by Carl Ritson in 197cc85253b6710538f7484b3e140a12c100af9b (10627). I'll commit the final fix once it's available.

        Show
        Erik Brangs added a comment - Committed quick fiy by Carl Ritson in 197cc85253b6710538f7484b3e140a12c100af9b (10627). I'll commit the final fix once it's available.
        Hide
        Erik Brangs added a comment -

        The original issue has been fixed. Improvements are still possible but they should not block a release.

        Show
        Erik Brangs added a comment - The original issue has been fixed. Improvements are still possible but they should not block a release.
        Hide
        Erik Brangs added a comment -

        I'm downgrading the severity of this issue to minor because we have a workaround.

        Carl Ritson proposed a solution for the issue in the original thread. Here's a quote from the thread, edited for clarity:

        >> There are a number of approaches to dealing with this:
        >> 1. assume allocation will always be top-down and ignore,
        >> 2. explicitly allocate thread stacks (these can be passed to pthread_create),
        >> 3. replace use of setjmp/longjmp with savecontext/swapcontext
        >> (although these are deprecated in POSIX),
        >> 4. implement a local version of longjmp without a check,
        >> 5. bypass the __longjmp_chk by using glibc's internal __libc_longjmp().
        >>

        My opinion is (4) the best option as (2) requires the bootImageRunner
        to allocate memory at a specific place in memory and manage it
        (because thread heap will need to be freed). Instead of
        reimplementing setjmp/longjmp completely, bootThread already has to be
        implemented in machine specific assembly to pivot the stack when
        entering the VM, the existing code should hence be extended to allow
        for pivoting back onto the thread stack. In effect bootThread should
        return when sysThreadTerminate is called.

        Show
        Erik Brangs added a comment - I'm downgrading the severity of this issue to minor because we have a workaround. Carl Ritson proposed a solution for the issue in the original thread. Here's a quote from the thread, edited for clarity: >> There are a number of approaches to dealing with this: >> 1. assume allocation will always be top-down and ignore, >> 2. explicitly allocate thread stacks (these can be passed to pthread_create), >> 3. replace use of setjmp/longjmp with savecontext/swapcontext >> (although these are deprecated in POSIX), >> 4. implement a local version of longjmp without a check, >> 5. bypass the __longjmp_chk by using glibc's internal __libc_longjmp(). >> My opinion is (4) the best option as (2) requires the bootImageRunner to allocate memory at a specific place in memory and manage it (because thread heap will need to be freed). Instead of reimplementing setjmp/longjmp completely, bootThread already has to be implemented in machine specific assembly to pivot the stack when entering the VM, the existing code should hence be extended to allow for pivoting back onto the thread stack. In effect bootThread should return when sysThreadTerminate is called.
        Hide
        Erik Brangs added a comment -

        A patch that implements the proposed solution hasn't arrived yet and I'd rather not provide patches for the bootimage runner code at this time. That's why I'm setting this issue to unassigned again.

        Show
        Erik Brangs added a comment - A patch that implements the proposed solution hasn't arrived yet and I'd rather not provide patches for the bootimage runner code at this time. That's why I'm setting this issue to unassigned again.

          People

          • Assignee:
            Unassigned
            Reporter:
            Erik Brangs
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated: