Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 23 Dec 1998 13:12:14 -0800 (PST)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        Matthew Dillon <dillon@apollo.backplane.com>
Cc:        Peter Jeremy <peter.jeremy@auss2.alcatel.com.au>, freebsd-security@FreeBSD.ORG
Subject:   Re: cvs commit: src/etc rc.conf
Message-ID:  <199812232112.NAA17044@apollo.backplane.com>

next in thread | raw e-mail | index | archive | help
    Ok, I've looked at it some more.   It isn't as bad as I thought but it
    is still pretty bad.

    Here's the problem:

    process A:
	    make unix domain connection
	    sendmsg a couple of file descriptors
	    close the descriptors we just sent
	    close the connection

	    (unc_gc() runs at this point and tries to flush/close these
	    descriptors, but doesn't quite do it right.  However, I looked
	    all the way back to the 4.4 lite commit and it does not appear
	    to gatuitously close the descriptors.  Instead, it relies on
	    sorflush() to do that).

    process B:
	    create socket, listen on socket.

	    wait until A has made the connection, sent the descriptors,
	    and closed its connection.

	    accept() the connection from A (which is now closed on A's) side.

	    recvmsg() descriptors, which were previously closed but may now
	    be valid again and hold references to files used by other processes
	    if we have waited a sufficient period of time.  However, from my
	    reading of the code if these descriptors had been closed, the
	    associated socket buffer would have been flushed so this can't 
	    happen.

    Ok, and this is why it *DOESN'T* actually happen:

	    unc_gc() adds an f_count reference, then attempt to
	    sorflush() the isolated files, then closes them (subtracting one
	    from the ref count).

	    Thus it is left up to sorflush() to actually close the descriptors.
	    sorflush() will release the associated messages so we should be 
	    safe.

    But here's the problem:

	     unp_gc() is confused.  It is calling sorflush() on non-sockets.

	     Line 1118 of kern/uipc_usrreq.c:

	/*
         * for each FD on our hit list, do the following two things 
         */      
        for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
                sorflush((struct socket *)(*fpp)->f_data);	<-------
        for (i = nunref, fpp = extra_ref; --i >= 0; ++fpp)
                closef(*fpp, (struct proc *) NULL);
        free((caddr_t)extra_ref, M_FILE);
        unp_gcing = 0;

	     It happily believes that any descriptor for which FMARK has not
	     been set is not marked accessible and thus, somehow, is magically
	     a socket and calls sorflush() on it.

	     But the descriptors that were queued in those sendmsg()'s wind
	     up not being FMARK's because their f_count == f_msgcount.
	     unp_gc() then assumes these descriptors are unix domain sockets.

	     But they are not necessarily unix domain sockets.

    Could someone take a look at that and tell me if I am right in regards
    to the sorflush() ?

::At the bottom of page 389:
::   "If a listening socket is accessible, then any queued connections
::    that it holds are also accessible; the garbage collector in 4.4BSD
::    fails to take this into account."
::
::This footnote is referenced from a paragraph discussing unp_gc() -
::which can be found in kern/uipc_usrreq.c.  From a quick look at the
::2.2.6 CVS logs (the latest I can quickly study), it doesn't look like
::it's ever been eradicated.
::
::Peter
:
:    Shit.  There's a bug.  It took me a while to find it, but there's a
:    bug.  A very bad bug.  A Very, very, very, very bad bug.  I'm going to
:    fix this in the FreeBSD tree first, then post the diff without 
:    additional comment.
:
:						-Matt


    Matthew Dillon  Engineering, HiWay Technologies, Inc. & BEST Internet 
                    Communications & God knows what else.
    <dillon@backplane.com> (Please include original email in any response)    

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-security" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199812232112.NAA17044>