[PATCH] Fix use after free in closedir

Corinna Vinschen vinschen@redhat.com
Wed Nov 13 15:17:00 GMT 2013


Hi Federico,

On Nov 13 12:22, Federico Terraneo wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> closedir() calls _cleanupdir() on a pointer to DIR after a free().
> If HAVE_DD_LOCK is defined, it also dereferences the pointer when
> calling __lock_release_recursive() and __lock_close_recursive().
> This was creating problems in my target.
> 
> Moreover, the previous code would not deallocate the struct if
> dirp->dd_fd is -1.
> 
> Attached is a simple patch to fix the issue.

Thanks!  I think you found something very suspicious here.  The test for
fd != -1 is supposed to check... what?

Opendir fails if open on the directory fails, so a valid DIR* also has a
valid dd_fd value.  The only time dd_fd can be -1 programatically is
when closedir has been called and in this case DIR* is invalid, too.
Or, if two threads call closedir for the same DIR* at about the same
time, one of them could find that dd_fd is -1 and skip the close/free
stuff.  However, the code

  fd = dirp->dd_fd;
  if (fd != -1) {
    dirp->dd_fd = -1;

is definitely not thread-safe, and closedir is not *supposed* to be
reentrant or thread-safe.

This test doesn't make sense.  libc/sys/sparc64/closedir.c and
libc/sys/sysvi386/closedir.c both don't perform it either.

What I would suggest is to simplify the call to this code instead:

    int
    _DEFUN(closedir, (dirp),
	   register DIR *dirp)
    {
	    int fd, rc;

    #ifdef HAVE_DD_LOCK
	    __lock_acquire_recursive(dirp->dd_lock);
    #endif
	    fd = dirp->dd_fd;
	    rc = close(fd);
	    _cleanupdir(dirp);
	    (void)free((void *)dirp->dd_buf);
    #ifdef HAVE_DD_LOCK
	    __lock_release_recursive(dirp->dd_lock);
	    __lock_close_recursive(dirp->dd_lock);
    #endif
	    (void)free((void *)dirp);
	    return rc;
    }

Does that make sense?  Did I miss something?


Thanks,
Corinna

-- 
Corinna Vinschen
Cygwin Maintainer
Red Hat
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://sourceware.org/pipermail/newlib/attachments/20131113/a6117c70/attachment.sig>


More information about the Newlib mailing list