Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 21 Jan 2006 02:29:00 -0800 (PST)
From:      Seth Kingsley <sethk@meowfishies.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   kern/92091: [patch] IP address hash corruption bug
Message-ID:  <20060121102900.05CC3DA8C0@toxic.magnesium.net>
Resent-Message-ID: <200601211030.k0LAU32Q088569@freefall.freebsd.org>

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

>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@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:



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