From owner-freebsd-bugs@FreeBSD.ORG Tue Jul 29 14:10:03 2008 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CFE8A106568D for ; Tue, 29 Jul 2008 14:10:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 77B688FC17 for ; Tue, 29 Jul 2008 14:10:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m6TEA3aL058432 for ; Tue, 29 Jul 2008 14:10:03 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m6TEA34p058431; Tue, 29 Jul 2008 14:10:03 GMT (envelope-from gnats) Resent-Date: Tue, 29 Jul 2008 14:10:03 GMT Resent-Message-Id: <200807291410.m6TEA34p058431@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Steve Sears Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9AD9C1065673 for ; Tue, 29 Jul 2008 14:09:41 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 896978FC14 for ; Tue, 29 Jul 2008 14:09:41 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.2/8.14.2) with ESMTP id m6TE9fRC091139 for ; Tue, 29 Jul 2008 14:09:41 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.2/8.14.1/Submit) id m6TE9f3m091138; Tue, 29 Jul 2008 14:09:41 GMT (envelope-from nobody) Message-Id: <200807291409.m6TE9f3m091138@www.freebsd.org> Date: Tue, 29 Jul 2008 14:09:41 GMT From: Steve Sears To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/126075: Network: internet control accesses beyond end of structure X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 29 Jul 2008 14:10:03 -0000 >Number: 126075 >Category: kern >Synopsis: Network: internet control accesses beyond end of structure >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Jul 29 14:10:03 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Steve Sears >Release: 6.1, 7.0 >Organization: NetApp >Environment: n/a >Description: In the kernel in sys/netinet/in.c: in_control() we have the following code, marked at the problem area: * If an alias address was specified, find that one instead of * the first one on the interface, if possible. */ if (ifp) { dst = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr; LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash) if (iap->ia_ifp == ifp && iap->ia_addr.sin_addr.s_addr == dst.s_addr) { ia = iap; break; } if (ia == NULL) TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { -> iap = ifatoia(ifa); -> if (iap->ia_addr.sin_family == AF_INET) { -> ia = iap; -> break; } } } The macro ifatoia() is a simple cast: #define ifatoia(ifa) ((struct in_ifaddr *)(ifa)) Now look at the structure def for in_ifaddr: struct in_ifaddr { struct ifaddr ia_ifa; /* protocol-independent info */ #define ia_ifp ia_ifa.ifa_ifp #define ia_flags ia_ifa.ifa_flags /* ia_{,sub}net{,mask} in host order */ u_long ia_net; /* network number of interface */ u_long ia_netmask; /* mask of net part */ u_long ia_subnet; /* subnet number, including net */ u_long ia_subnetmask; /* mask of subnet part */ struct in_addr ia_netbroadcast; /* to recognize net broadcasts */ LIST_ENTRY(in_ifaddr) ia_hash; /* entry in bucket of inet addresses */ TAILQ_ENTRY(in_ifaddr) ia_link; /* list of internet addresses */ struct sockaddr_in ia_addr; /* reserve space for interface name */ struct sockaddr_in ia_dstaddr; /* reserve space for broadcast addr */ #define ia_broadaddr ia_dstaddr struct sockaddr_in ia_sockmask; /* reserve space for general netmask */ }; All of the internet types include an ifaddr at the beginning, but it accessing beyond this struct after a cast is not a safe operation. >How-To-Repeat: Use non AF_INET network interfaces. >Fix: The problem is that ia_addr is not part of the overloaded ifaddr structure, so this check falls off the end of the structure in all but the in_ifaddr case. The corrected code should be: if (ia == NULL) TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) { + if (ifa->ifa_addr->sa_family == AF_INET) { + ia = ifatoia(ifa); + break; + } This prevents bogus data being returned due to a cast allowing the code to walk off the end of valid data. >Release-Note: >Audit-Trail: >Unformatted: