kern/92091: [patch] IP address hash corruption bug

Seth Kingsley sethk at meowfishies.com
Sat Jan 21 02:30:05 PST 2006


>Number:         92091
>Category:       kern
>Synopsis:       [patch] IP address hash corruption bug
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Jan 21 10:30:03 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Seth Kingsley
>Release:        FreeBSD 5.4-RELEASE i386
>Organization:
>Environment:
System: FreeBSD neko.home.meowfishies.com 5.4-RELEASE FreeBSD 5.4-RELEASE #1:
Sat Jan 14 22:37:52 UTC 2006
sethk at neko.home.meowfishies.com:/usr/src/sys/i386/compile/GENERIC  i386

>Description:
	You can cause a panic (page fault) by supplying a non AF_INET address
	as parameter to SIOCSIFADDR.  The command will fail, removing the
	temporary address from the IP hash, which it was never added to.

>How-To-Repeat:

#include    <sys/types.h>
#include    <sys/socket.h>
#include    <sys/sockio.h>
#include    <net/if.h>
#include    <netinet/in.h>

#include    <stdio.h>
#include    <sysexits.h>
#include    <err.h>

int
main(int ac, char *av[])
{
    const char *ifname;
    int sfd;
    struct ifreq ifr;
    register int i;

    if (ac != 2)
    {
	fprintf(stderr, "usage: %s <ifname>\n", getprogname());
	return EX_USAGE;
    }

    if ((sfd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
	err(EX_OSERR, "create socket");

    bzero(&ifr, sizeof(ifr));
    strlcpy(ifr.ifr_name, av[1], sizeof(ifr.ifr_name));
    ifr.ifr_addr.sa_len = 0;
    ifr.ifr_addr.sa_family = AF_MAX;
    for (i = 0; i < 2; ++i)
	if (ioctl(sfd, SIOCSIFADDR, &ifr) == -1)
	    err(EX_OSERR, "SIOCSIFADDR");

    close(sfd);

    return EX_OK;
}

>Fix:
	Only remove the temporary in_ifaddr structure from the hash if it is
	actually an AF_INET address:

--- /sys/netinet/in.c.orig	Sun Jan 22 02:16:39 2006
+++ /sys/netinet/in.c	Sun Jan 22 02:17:14 2006
@@ -466,7 +466,8 @@
 	s = splnet();
 	TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
 	TAILQ_REMOVE(&in_ifaddrhead, ia, ia_link);
-	LIST_REMOVE(ia, ia_hash);
+	if (ia->ia_addr.sin_family == AF_INET)
+		LIST_REMOVE(ia, ia_hash);
 	IFAFREE(&ia->ia_ifa);
 	splx(s);
 
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list