summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPaul Jakma <paul.jakma@hpe.com>2016-02-09 15:23:03 +0000
committerPaul Jakma <paul.jakma@hpe.com>2016-03-08 17:53:22 +0000
commitbf83fa25f1bddec6f09ad879cba5e975a3ae5495 (patch)
treea01a0137a4193d2d33d61bb43c113afef3e421a6 /lib
parent2db962760426ddb9e266f9a4bc0b274584c819cc (diff)
downloadquagga-bf83fa25f1bddec6f09ad879cba5e975a3ae5495.tar.bz2
quagga-bf83fa25f1bddec6f09ad879cba5e975a3ae5495.tar.xz
lib: Check prefix length from zebra is sensible
* zclient.c: prefix length on router-id and interface address add messages not sanity checked. fix. * */*_zebra.c: Prefix length on zebra route read was not checked, and clients use it to write to storage. An evil zebra could overflow client structures by sending overly long prefixlen. Prompted by discussions with: Donald Sharp <sharpd@cumulusnetworks.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/zclient.c45
1 files changed, 28 insertions, 17 deletions
diff --git a/lib/zclient.c b/lib/zclient.c
index 610008b4..d25c8d44 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -651,18 +651,30 @@ zebra_redistribute_send (int command, struct zclient *zclient, int type,
return zclient_send_message(zclient);
}
+/* Get prefix in ZServ format; family should be filled in on prefix */
+static void
+zclient_stream_get_prefix (struct stream *s, struct prefix *p)
+{
+ size_t plen = prefix_blen (p);
+ u_char c;
+ p->prefixlen = 0;
+
+ if (plen == 0)
+ return;
+
+ stream_get (&p->u.prefix, s, plen);
+ c = stream_getc(s);
+ p->prefixlen = MIN(plen * 8, c);
+}
+
/* Router-id update from zebra daemon. */
void
zebra_router_id_update_read (struct stream *s, struct prefix *rid)
{
- int plen;
-
/* Fetch interface address. */
rid->family = stream_getc (s);
-
- plen = prefix_blen (rid);
- stream_get (&rid->u.prefix, s, plen);
- rid->prefixlen = stream_getc (s);
+
+ zclient_stream_get_prefix (s, rid);
}
/* Interface addition from zebra daemon. */
@@ -814,8 +826,7 @@ zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id)
ifindex_t ifindex;
struct interface *ifp;
struct connected *ifc;
- struct prefix p, d;
- int family;
+ struct prefix p, d, *dp;
int plen;
u_char ifc_flags;
@@ -840,21 +851,21 @@ zebra_interface_address_read (int type, struct stream *s, vrf_id_t vrf_id)
ifc_flags = stream_getc (s);
/* Fetch interface address. */
- family = p.family = stream_getc (s);
-
- plen = prefix_blen (&p);
- stream_get (&p.u.prefix, s, plen);
- p.prefixlen = stream_getc (s);
+ d.family = p.family = stream_getc (s);
+ plen = prefix_blen (&d);
+
+ zclient_stream_get_prefix (s, &p);
/* Fetch destination address. */
stream_get (&d.u.prefix, s, plen);
- d.family = family;
-
+
+ /* N.B. NULL destination pointers are encoded as all zeroes */
+ dp = memconstant(&d.u.prefix,0,plen) ? NULL : &d;
+
if (type == ZEBRA_INTERFACE_ADDRESS_ADD)
{
/* N.B. NULL destination pointers are encoded as all zeroes */
- ifc = connected_add_by_prefix(ifp, &p,(memconstant(&d.u.prefix,0,plen) ?
- NULL : &d));
+ ifc = connected_add_by_prefix(ifp, &p, dp);
if (ifc != NULL)
{
ifc->flags = ifc_flags;