aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGordon Tetlow <gordon@FreeBSD.org>2020-03-19 16:50:36 +0000
committerGordon Tetlow <gordon@FreeBSD.org>2020-03-19 16:50:36 +0000
commitfcfa8e1efd4ccee4a497806c4eed5c71d2071b4c (patch)
treef13085eb8be6c4aeb1b24dcc1c22c9c501fe927d
parent9842ed8859172c3553bc3d833fec8bca73256ea6 (diff)
downloadsrc-fcfa8e1efd4ccee4a497806c4eed5c71d2071b4c.tar.gz
src-fcfa8e1efd4ccee4a497806c4eed5c71d2071b4c.zip
Fix incorrect user-controlled pointer use in epair.
Approved by: so Security: FreeBSD-SA-20:07.epair Security: CVE-2020-7452
Notes
Notes: svn path=/releng/12.1/; revision=359141
-rw-r--r--sys/net/if_clone.c19
-rw-r--r--sys/net/if_clone.h3
-rw-r--r--sys/net/if_epair.c42
3 files changed, 35 insertions, 29 deletions
diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c
index 6207ff0c037e..acc392ead16a 100644
--- a/sys/net/if_clone.c
+++ b/sys/net/if_clone.c
@@ -211,6 +211,18 @@ if_clone_create(char *name, size_t len, caddr_t params)
return (if_clone_createif(ifc, name, len, params));
}
+void
+if_clone_addif(struct if_clone *ifc, struct ifnet *ifp)
+{
+
+ if ((ifc->ifc_flags & IFC_NOGROUP) == 0)
+ if_addgroup(ifp, ifc->ifc_name);
+
+ IF_CLONE_LOCK(ifc);
+ IFC_IFLIST_INSERT(ifc, ifp);
+ IF_CLONE_UNLOCK(ifc);
+}
+
/*
* Create a clone network interface.
*/
@@ -233,12 +245,7 @@ if_clone_createif(struct if_clone *ifc, char *name, size_t len, caddr_t params)
if (ifp == NULL)
panic("%s: lookup failed for %s", __func__, name);
- if ((ifc->ifc_flags & IFC_NOGROUP) == 0)
- if_addgroup(ifp, ifc->ifc_name);
-
- IF_CLONE_LOCK(ifc);
- IFC_IFLIST_INSERT(ifc, ifp);
- IF_CLONE_UNLOCK(ifc);
+ if_clone_addif(ifc, ifp);
}
return (err);
diff --git a/sys/net/if_clone.h b/sys/net/if_clone.h
index 5dceacf68e0f..b721e294119b 100644
--- a/sys/net/if_clone.h
+++ b/sys/net/if_clone.h
@@ -79,7 +79,8 @@ int if_clone_list(struct if_clonereq *);
struct if_clone *if_clone_findifc(struct ifnet *);
void if_clone_addgroup(struct ifnet *, struct if_clone *);
-/* The below interface used only by epair(4). */
+/* The below interfaces are used only by epair(4). */
+void if_clone_addif(struct if_clone *, struct ifnet *);
int if_clone_destroyif(struct if_clone *, struct ifnet *);
#endif /* _KERNEL */
diff --git a/sys/net/if_epair.c b/sys/net/if_epair.c
index b28fe2b4bd30..376bdbe9117f 100644
--- a/sys/net/if_epair.c
+++ b/sys/net/if_epair.c
@@ -711,6 +711,21 @@ epair_clone_match(struct if_clone *ifc, const char *name)
return (1);
}
+static void
+epair_clone_add(struct if_clone *ifc, struct epair_softc *scb)
+{
+ struct ifnet *ifp;
+ uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */
+
+ ifp = scb->ifp;
+ /* Copy epairNa etheraddr and change the last byte. */
+ memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN);
+ eaddr[5] = 0x0b;
+ ether_ifattach(ifp, eaddr);
+
+ if_clone_addif(ifc, ifp);
+}
+
static int
epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
{
@@ -723,24 +738,6 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
uint32_t hash;
uint8_t eaddr[ETHER_ADDR_LEN]; /* 00:00:00:00:00:00 */
- /*
- * We are abusing params to create our second interface.
- * Actually we already created it and called if_clone_create()
- * for it to do the official insertion procedure the moment we knew
- * it cannot fail anymore. So just do attach it here.
- */
- if (params) {
- scb = (struct epair_softc *)params;
- ifp = scb->ifp;
- /* Copy epairNa etheraddr and change the last byte. */
- memcpy(eaddr, scb->oifp->if_hw_addr, ETHER_ADDR_LEN);
- eaddr[5] = 0x0b;
- ether_ifattach(ifp, eaddr);
- /* Correctly set the name for the cloner list. */
- strlcpy(name, ifp->if_xname, len);
- return (0);
- }
-
/* Try to see if a special unit was requested. */
error = ifc_name2unit(name, &unit);
if (error != 0)
@@ -891,10 +888,11 @@ epair_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
if_setsendqready(ifp);
/* We need to play some tricks here for the second interface. */
strlcpy(name, epairname, len);
- error = if_clone_create(name, len, (caddr_t)scb);
- if (error)
- panic("%s: if_clone_create() for our 2nd iface failed: %d",
- __func__, error);
+
+ /* Correctly set the name for the cloner list. */
+ strlcpy(name, scb->ifp->if_xname, len);
+ epair_clone_add(ifc, scb);
+
scb->if_qflush = ifp->if_qflush;
ifp->if_qflush = epair_qflush;
ifp->if_transmit = epair_transmit;