[GHC] #8108: getGroupEntryForID in multi-threaded applications

GHC ghc-devs at haskell.org
Thu Aug 1 23:58:55 CEST 2013


#8108: getGroupEntryForID in multi-threaded applications
------------------------------------+-------------------------------------
       Reporter:  redneb            |             Owner:
           Type:  bug               |            Status:  new
       Priority:  normal            |         Milestone:
      Component:  libraries/unix    |           Version:  7.6.3
       Keywords:                    |  Operating System:  Unknown/Multiple
   Architecture:  Unknown/Multiple  |   Type of failure:  Runtime crash
     Difficulty:  Unknown           |         Test Case:
     Blocked By:                    |          Blocking:
Related Tickets:                    |
------------------------------------+-------------------------------------
 The following program

 {{{
 #!haskell
 import Control.Monad
 import Control.Concurrent
 import System.Posix.User

 main = do
     void $ forkIO $ forever $ getGroupEntryForID 0
     forever $ getGroupEntryForID 0
 }}}

 segfaults when executed after less than a second. I've confirmed this with
 HP-2013.2.0.0/GHC-7.63/unix-2.6.0.1 in many different linuxes as well as
 Mac OS X 10.8. After some digging I found the reason for this failure. The
 underlying posix function used by getGroupEntryForID is:

 {{{
 #!c
 int getgrgid_r(gid_t gid, struct group *grp, char *buf, size_t buflen,
 struct group **result);
 }}}

 getgrgid_r returns its result with its last argument which is a pointer to
 a struct. The struct has to be allocated by the caller as usual. The
 problem is that the struct contains several strings. This is what the char
 *buf argument is for; the caller is supposed to allocate a large enough
 buffer to be used by getgrgid_r to store those strings. Then the caller
 has to read the struct *before* the auxiliary string buffer is
 deallocated. What complicates things even more is that we don't know in
 advance the right size for that buffer; we have to pick an arbitrary size
 and then keep doubling it while getgrgid_r returns ERANGE. The current
 implementation of getGroupEntryForID uses allocaBytes to allocate that
 buffer but then it does not unpack the struct inside the allocaBytes
 block.

 The posix functions getgrnam_r, getpwuid_r and getpwnam_r (used by
 getGroupEntryForName, getUserEntryForID and getUserEntryForName
 respectively) operate in the same fashion and are susceptible to the same
 bug.

 I am really surprised that people haven't been hitting that issue earlier.

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




More information about the ghc-tickets mailing list