On Fri 2016-07-15 14:19:51 +0200, Maik Zumstrull wrote:
> Package: libnss-extrausers
> Version: 0.6-3
>
> The implementation uses three static global pointer variables:
>
> static FILE *groupsfile = NULL;
> static FILE *shadowfile = NULL;
> static FILE *usersfile = NULL;
>
> Since these are used without locks or atomic operations, this is not
> thread-safe, even though NSS functions are supposed to be
> reentrant. This is leading to occasional "double free or corruption"
> crashes in libvirtd for us, specifically in fclose(groupsfile); in
> _nss_extrausers_endgrent.
>
> As a quick fix, I suggest declaring these variables thread-local:
>
> static __thread FILE *groupsfile = NULL;
> static __thread FILE *shadowfile = NULL;
> static __thread FILE *usersfile = NULL;
>
> It's not necessarily the most elegant solution, but it should make the code 
> fully reentrant.

Are you sure this wouldn't cause the different thread's understanding of
the underlying file descriptors to get out of sync?  declaring them
thread-local wouldn't prevent them sharing the same file descriptor,
right?  i think it would just be thread-local buffering.

This seems like a way to cause some even more subtle bug, for example:

 thread A causes libnss-extrausers to scan the groups file for some
    value, and it reads up to block X, while
 thread B causes libnss-extrausers to scan the groups file for some
    other value, and it reads up to block Y

then thread A resumes; the underlying file descriptor is advanced to
position Y but the FILE* buffers in thread A have only cached enough
data to represent block X.  what happens then?

I could be misunderstanding the libnss-extrausers codebase, though --
feel free to clarify and correct!

    --dkg

Reply via email to