Quantcast

[GHC] #6059: FFI: segfault when jumping to code buffer (under certain conditions)

classic Classic list List threaded Threaded
4 messages Options
GHC
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

[GHC] #6059: FFI: segfault when jumping to code buffer (under certain conditions)

GHC
#6059: FFI: segfault when jumping to code buffer (under certain conditions)
---------------------------+------------------------------------------------
 Reporter:  guest          |          Owner:                
     Type:  bug            |         Status:  new          
 Priority:  normal         |      Component:  Compiler (FFI)
  Version:  7.4.1          |       Keywords:  segfault ffi  
       Os:  Linux          |   Architecture:  x86          
  Failure:  Runtime crash  |       Testcase:                
Blockedby:                 |       Blocking:                
  Related:                 |  
---------------------------+------------------------------------------------
 I updated my developing machine from Ubuntu 10.04 LTS to Ubuntu 12.04 LTS
 (or ghc 6.12.1 to ghc 7.4.1) and I run into a very strange behavior at my
 currenct project.

 After some hours, I reduced it to the following code:
 {{{
 {-# LANGUAGE ForeignFunctionInterface #-}
 module Main where

 import Data.Word
 import Text.Printf
 import Foreign

 foreign import ccall "dynamic"
    code_void :: FunPtr (IO ()) -> (IO ())

 main :: IO ()
 main = do
   entryPtr <- (mallocBytes 2)
   poke entryPtr (0xc390 :: Word16) -- nop (0x90); ret(0xc3) (little endian
 order)

   _ <- printf "entry point: 0x%08x\n" ((fromIntegral $ ptrToIntPtr
 entryPtr) :: Int)
   _ <- getLine -- for debugging
   code_void $ castPtrToFunPtr entryPtr
   putStrLn "welcome back"

 }}}
 I'm trying to generate some code at run-time, jump to it, and come back
 again. Using a Makefile, everything is fine:
 {{{
 $ make
 ghc --make -Wall -O2 Main.hs -o stackoverflow_segv
 [1 of 1] Compiling Main             ( Main.hs, Main.o )
 Linking stackoverflow_segv ...
 ./stackoverflow_segv
 entry point: 0x098d77e0

 welcome back
 }}}
 However, if I call the binary directly from the shell:
 {{{
 $ ./stackoverflow_segv
 entry point: 0x092547e0

 Segmentation fault (core dumped)
 }}}
 This behavior is reproducible (luckily?).

 Using gdb, objdump and /proc I figured out:
 {{{
 $ gdb -q stackoverflow_segv
 Reading symbols from /home/lewurm/stackoverflow/stackoverflow_segv...(no
 debugging symbols found)...done.
 (gdb) run
 Starting program: /home/lewurm/stackoverflow/stackoverflow_segv
 [Thread debugging using libthread_db enabled]
 Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
 entry point: 0x080fc810
 }}}
 before pressing enter, I switch to a second terminal:
 {{{
 $ cat /proc/`pgrep stackoverflow`/maps
 [...]
 08048000-080ea000 r-xp 00000000 08:01 2492678
 /home/lewurm/stackoverflow/stackoverflow_segv
 080ea000-080eb000 r--p 000a2000 08:01 2492678
 /home/lewurm/stackoverflow/stackoverflow_segv
 080eb000-080f1000 rw-p 000a3000 08:01 2492678
 /home/lewurm/stackoverflow/stackoverflow_segv
 080f1000-08115000 rw-p 00000000 00:00 0          [heap]
 [...]
 }}}
 and back again:
 {{{
 <enter>
 Program received signal SIGSEGV, Segmentation fault.
 0x0804ce3c in s2aV_info ()
 }}}
 Boo. Let's see what this code does:
 {{{
 $ objdump -D stackoverflow_segv | grep -C 3 804ce3c
  804ce31:       89 44 24 4c             mov    %eax,0x4c(%esp)
  804ce35:       83 ec 0c                sub    $0xc,%esp
  804ce38:       8b 44 24 4c             mov    0x4c(%esp),%eax
  804ce3c:       ff d0                   call   *%eax
  804ce3e:       83 c4 0c                add    $0xc,%esp
  804ce41:       83 ec 08                sub    $0x8,%esp
  804ce44:       8b 44 24 54             mov    0x54(%esp),%eax
 }}}
 uhm, jumping to *%eax. What was %eax again?
 {{{
  (gdb) info reg eax
  eax            0x80fc810        135251984
 }}}
 Well, actually it's just the code buffer. Looking up /proc/*/maps tells
 us, that this page isn't executeable (rw-p, right?). But, it's the same
 situation when executing it within make.

 What is wrong here?


 The code is also available via a [https://gist.github.com/2503293 gist]

 First, I posted this issue to [http://stackoverflow.com/questions/10341943
 /ghc-segmentation-fault-under-strange-conditions stackoverflow], since I
 wasn't sure what causes this issue and I don't thought it would be a
 problem with GHC. But (read the comments there please), as it turns out,
 with older releases of GHC (e.g. 7.2.2) it works for me.

 Some Information about the used system:
 {{{
 $ ghc --version
 The Glorious Glasgow Haskell Compilation System, version 7.4.1
 $ gcc --version
 gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
 Copyright (C) 2011 Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.  There is NO
 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.

 $ make --version
 GNU Make 3.81
 Copyright (C) 2006  Free Software Foundation, Inc.
 This is free software; see the source for copying conditions.
 There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
 PARTICULAR PURPOSE.

 This program built for i686-pc-linux-gnu
 $ uname -a
 Linux matevm-dev 3.2.0-23-generic #36-Ubuntu SMP Tue Apr 10 20:41:14 UTC
 2012 i686 athlon i386 GNU/Linux
 $ cat /etc/issue
 Ubuntu 12.04 LTS \n \l
 }}}

--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/6059>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
GHC
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [GHC] #6059: FFI: segfault when jumping to code buffer (under certain conditions)

GHC
#6059: FFI: segfault when jumping to code buffer (under certain conditions)
-------------------------------+--------------------------------------------
    Reporter:  guest           |       Owner:              
        Type:  bug             |      Status:  new          
    Priority:  normal          |   Milestone:              
   Component:  Compiler (FFI)  |     Version:  7.4.1        
    Keywords:  segfault ffi    |          Os:  Linux        
Architecture:  x86             |     Failure:  Runtime crash
  Difficulty:  Unknown         |    Testcase:              
   Blockedby:                  |    Blocking:              
     Related:                  |  
-------------------------------+--------------------------------------------
Changes (by simonmar):

  * difficulty:  => Unknown


Comment:

 If I understand correctly, you're asking why the program sometimes works,
 not why it sometimes fails?  It is expected that jumping to ordinary
 memory might crash.

 In the GHC RTS we have a function `allocateExec()` for allocating
 executable memory.  Internally it calls into `libffi` which has all sorts
 of hacks to make this work.

 If you want we could make `allocateExec()` visible from Haskell, though it
 needs an explicit `freeExec()` (you can't allocate garbage-collectable
 executable memory).

--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/6059#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
GHC
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [GHC] #6059: FFI: segfault when jumping to code buffer (under certain conditions)

GHC
In reply to this post by GHC
#6059: FFI: segfault when jumping to code buffer (under certain conditions)
-------------------------------+--------------------------------------------
    Reporter:  guest           |       Owner:              
        Type:  bug             |      Status:  new          
    Priority:  normal          |   Milestone:  7.6.1        
   Component:  Compiler (FFI)  |     Version:  7.4.1        
    Keywords:  segfault ffi    |          Os:  Linux        
Architecture:  x86             |     Failure:  Runtime crash
  Difficulty:  Unknown         |    Testcase:              
   Blockedby:                  |    Blocking:              
     Related:                  |  
-------------------------------+--------------------------------------------
Changes (by simonmar):

  * milestone:  => 7.6.1


--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/6059#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
GHC
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate

Re: [GHC] #6059: FFI: segfault when jumping to code buffer (under certain conditions)

GHC
In reply to this post by GHC
#6059: FFI: segfault when jumping to code buffer (under certain conditions)
-----------------------------+----------------------------------------------
  Reporter:  guest           |          Owner:              
      Type:  bug             |         Status:  closed      
  Priority:  normal          |      Milestone:  7.6.1      
 Component:  Compiler (FFI)  |        Version:  7.4.1      
Resolution:  invalid         |       Keywords:  segfault ffi
        Os:  Linux           |   Architecture:  x86        
   Failure:  Runtime crash   |     Difficulty:  Unknown    
  Testcase:                  |      Blockedby:              
  Blocking:                  |        Related:              
-----------------------------+----------------------------------------------
Changes (by guest):

  * status:  new => closed
  * resolution:  => invalid


Comment:

 Well, as I said, it's reproducible (at least on my system). Within `make`
 it works as desired, but calling it from shell, it doesn't.

 I looked at the implementation of `mallocBytes`. It's just calling
 `malloc`, so a came up with this code:
 {{{
 #!C
 #include <stdio.h>
 #include <stdlib.h>

 int main(void)
 {
         unsigned short *ptr = (unsigned short*) malloc(2);
         *ptr = 0xc390;
         printf("entry point: 0x%08x\n", (unsigned short) ptr);
         ((void (*)()) ptr) ();
         printf("welcome back\n");
 }
 }}}
 Same behaviour: Calling it from `make`, everything is fine. Calling it
 from shell, segfault.
 So I guess it isn't GHC related at all. Sorry :-/ I think this ticket can
 be closed.


 The solution for my project was, allocate memory and mark it as executable
 with `mprotect`.


 Thanks,
 bernhard

--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/6059#comment:3>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler

_______________________________________________
Glasgow-haskell-bugs mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs
Loading...