Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Mar 2013 19:31:05 GMT
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/176764: [net] [if_bridge] use-after-free in if_bridge
Message-ID:  <201303081931.r28JV5B9070805@red.freebsd.org>
Resent-Message-ID: <201303081940.r28Je3mZ034132@freefall.freebsd.org>

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

>Number:         176764
>Category:       misc
>Synopsis:       [net] [if_bridge] use-after-free in if_bridge
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Mar 08 19:40:03 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator:     Adrian Chadd
>Release:        
>Organization:
>Environment:
>Description:
Hi Adrian,

There seems to be a potential use-after-free in `sys/net/if_bridge.c'.
>From the following chunk of code:

#define GRAB_OUR_PACKETS(iface) \
        if ((iface)->if_type == IFT_GIF) \
                continue; \
        /* It is destined for us. */ \
        if (memcmp(IF_LLADDR((iface)), eh->ether_dhost,  ETHER_ADDR_LEN) == 0 \
            OR_CARP_CHECK_WE_ARE_DST((iface))                           \
            ) {                                                         \
                if ((iface)->if_type == IFT_BRIDGE) {                   \
                        ETHER_BPF_MTAP(iface, m);                       \
                        iface->if_ipackets++;                           \
                        /* Filter on the physical interface. */         \
                        if (pfil_local_phys &&                          \
                            (PFIL_HOOKED(&V_inet_pfil_hook)             \
                             OR_PFIL_HOOKED_INET6)) {                   \
                                if (bridge_pfil(&m, NULL, ifp,          \
                                    PFIL_IN) != 0 || m == NULL) {       \
                                        BRIDGE_UNLOCK(sc);              \
                                        return (NULL);                  \
                                }                                       \
                        }                                               \
                }                                                       \

bridge_pfil() might end-up changing the mbuf pointer (and the
underlying data), however, we still have a pending pointer to the data
through `eh' which is about to be dereferenced in the following call
to bridge_rtupdate():

                if (bif->bif_flags & IFBIF_LEARNING) {                  \
                        error = bridge_rtupdate(sc, eh->ether_shost,    \
                            vlan, bif, 0, IFBAF_DYNAMIC);               \

The obvious patch to fix this is attached to this mail.

>How-To-Repeat:
n/a
>Fix:
see attachment

Patch attached with submission follows:

diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index 85ad9fb..73ee550 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -2313,6 +2313,7 @@ bridge_input(struct ifnet *ifp, struct mbuf *m)
 					BRIDGE_UNLOCK(sc);		\
 					return (NULL);			\
 				}					\
+				eh = mtod(m, struct ether_header *);	\
 			}						\
 		}							\
 		if (bif->bif_flags & IFBIF_LEARNING) {			\


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



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