This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix use after free in closedir


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

Attachment: pgppNAk4UiMXq.pgp
Description: PGP signature


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]