Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 30 Jul 2001 16:20:54 -0700 (PDT)
From:      Richard Andrades <richard@xebeo.com>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   kern/29336: non-privileged user opening routing socket causes resource leak
Message-ID:  <200107302320.f6UNKsu93862@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         29336
>Category:       kern
>Synopsis:       non-privileged user opening routing socket causes resource leak
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 30 16:30:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Richard Andrades
>Release:        RELENG_4_1_1_RELEASE (Revision 1.1.2.2)
>Organization:
Xebeo Communications, Inc.
>Environment:
FreeBSD X2.xebeo.com 4.1.1 FreeBSD 4.1.1 #11: Tue Jul 17 14:47:29 EDT 2001     richard@X2.xebeo.com:/net/scratch/richard/kern/kernel/sys/compile/GENERIC  i386
>Description:
If a routing socket is opened without root permissions, the socket() 
call fails. But the kernel fails to free the socket structure which 
it already allocated at the begining of the system call. This causes
a resource leak in the socket table. If this happens often enough,
the system runs out of socket descriptors and is unable to start
any new network operations.
>How-To-Repeat:
Run:
---------------------------------------
main()
{
    for(;;)
        socket(AF_ROUTE, SOCK_RAW, 0); 
}
---------------------------------------
as a non-root user.

>Fix:
Note: I checked the latest version and this bug has not yet been fixed.

FILE: src/sys/net/rtsock.c
Function: rts_attach()        
---Begin code fragment----------------------------------------
        MALLOC(rp, struct rawcb *, sizeof *rp, M_PCB, M_WAITOK); /* XXX */
        if (rp == 0)
                return ENOBUFS;
        bzero(rp, sizeof *rp);

        /*
         * The splnet() is necessary to block protocols from sending
         * error notifications (like RTM_REDIRECT or RTM_LOSING) while
         * this PCB is extant but incompletely initialized.
         * Probably we should try to do more of this work beforehand and
         * eliminate the spl.
         */
        s = splnet();
        so->so_pcb = (caddr_t)rp;
        error = raw_usrreqs.pru_attach(so, proto, p); /* NOTE: Will return error if not root */
        rp = sotorawcb(so);
        if (error) {
/* Begin BUG FIX */
                so->so_pcb = 0; /* Otherwise the socket won't be freed */
/* End BUG FIX */
                splx(s);
                free(rp, M_PCB);
                return error;
        }
---End code fragment------------------------------------------------


Explanation:
************

In the function socreate() in the file src/sys/kern/uipc_socket.c
there is the following code fragment:
-----------------------------
        error = (*prp->pr_usrreqs->pru_attach)(so, proto, p); /* NOTE: This goes to rts_attach() */
        if (error) {
                so->so_state |= SS_NOFDREF;
                sofree(so);
                return (error);
        }        
------------------------------------

Looking at the function sofree() in the same file, we find:
-------------------------------------
void
sofree(so)
        register struct socket *so;
{
        struct socket *head = so->so_head;

        if (so->so_pcb || (so->so_state & SS_NOFDREF) == 0)
                return; 
-----------------------------------

So if rts_attach() fails to reset the so_pcb member, sofree()
will not free the socket.


>Release-Note:
>Audit-Trail:
>Unformatted:

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




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