Skip to content

getGroupEntryForID segfaults in multi-threaded applications

The following program

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:

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.

Trac metadata
Trac field Value
Version 7.6.3
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component libraries/unix
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
Edited by redneb
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information