From 930571d24f051e2088b76e7e9eeed58b2bb51455 Mon Sep 17 00:00:00 2001 From: Stephen Worley Date: Fri, 20 Jul 2018 23:20:28 -0400 Subject: [PATCH] zebra: Add check for prefix length from kernel messages Zebra needed a check that varifies the prefix length of an address is a valid length when receiving route changes and interface address changes. Signed-off-by: Stephen Worley --- zebra/if_netlink.c | 12 ++++++++++++ zebra/rt_netlink.c | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index 8f6e31cfa8..67b6704d6e 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -991,6 +991,12 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) /* Register interface address to the interface. */ if (ifa->ifa_family == AF_INET) { + if (ifa->ifa_prefixlen > IPV4_MAX_BITLEN) { + zlog_warn( + "Invalid prefix length: %d received from kernel interface addr change: %d", + ifa->ifa_prefixlen, h->nlmsg_type); + return 0; + } if (h->nlmsg_type == RTM_NEWADDR) connected_add_ipv4(ifp, flags, (struct in_addr *)addr, ifa->ifa_prefixlen, @@ -1001,6 +1007,12 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup) ifa->ifa_prefixlen, (struct in_addr *)broad); } if (ifa->ifa_family == AF_INET6) { + if (ifa->ifa_prefixlen > IPV6_MAX_BITLEN) { + zlog_warn( + "Invalid prefix length: %d received from kernel interface addr change: %d", + ifa->ifa_prefixlen, h->nlmsg_type); + return 0; + } if (h->nlmsg_type == RTM_NEWADDR) { /* Only consider valid addresses; we'll not get a * notification from diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 485abc3f12..8393ba6f24 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -384,17 +384,36 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id, if (rtm->rtm_family == AF_INET) { p.family = AF_INET; + if (rtm->rtm_dst_len > IPV4_MAX_BITLEN) { + zlog_warn( + "Invalid destination prefix length: %d received from kernel route change", + rtm->rtm_dst_len); + return 0; + } memcpy(&p.u.prefix4, dest, 4); p.prefixlen = rtm->rtm_dst_len; src_p.prefixlen = 0; // Forces debug below to not display anything + } else if (rtm->rtm_family == AF_INET6) { p.family = AF_INET6; + if (rtm->rtm_dst_len > IPV6_MAX_BITLEN) { + zlog_warn( + "Invalid destination prefix length: %d received from kernel route change", + rtm->rtm_dst_len); + return 0; + } memcpy(&p.u.prefix6, dest, 16); p.prefixlen = rtm->rtm_dst_len; src_p.family = AF_INET6; + if (rtm->rtm_src_len > IPV6_MAX_BITLEN) { + zlog_warn( + "Invalid source prefix length: %d received from kernel route change", + rtm->rtm_src_len); + return 0; + } memcpy(&src_p.prefix, src, 16); src_p.prefixlen = rtm->rtm_src_len; } -- 2.39.5