From owner-svn-src-all@FreeBSD.ORG Wed Dec 8 15:12:37 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8D4FE1065670; Wed, 8 Dec 2010 15:12:37 +0000 (UTC) (envelope-from glebius@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7C0C68FC23; Wed, 8 Dec 2010 15:12:37 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id oB8FCb10007046; Wed, 8 Dec 2010 15:12:37 GMT (envelope-from glebius@svn.freebsd.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id oB8FCblT007044; Wed, 8 Dec 2010 15:12:37 GMT (envelope-from glebius@svn.freebsd.org) Message-Id: <201012081512.oB8FCblT007044@svn.freebsd.org> From: Gleb Smirnoff Date: Wed, 8 Dec 2010 15:12:37 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r216297 - head/sbin/route X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Dec 2010 15:12:37 -0000 Author: glebius Date: Wed Dec 8 15:12:37 2010 New Revision: 216297 URL: http://svn.freebsd.org/changeset/base/216297 Log: - Fix array bounds checking. [1] - Add message length checking. PR: 151664 [1] Submitted by: Alexey Illarionov [1] Reviewed by: yar Modified: head/sbin/route/route.c Modified: head/sbin/route/route.c ============================================================================== --- head/sbin/route/route.c Wed Dec 8 15:10:27 2010 (r216296) +++ head/sbin/route/route.c Wed Dec 8 15:12:37 2010 (r216297) @@ -115,11 +115,11 @@ static void mask_addr(void); static void monitor(void); static const char *netname(struct sockaddr *); static void newroute(int, char **); -static void pmsg_addrs(char *, int); -static void pmsg_common(struct rt_msghdr *); +static void pmsg_addrs(char *, int, size_t); +static void pmsg_common(struct rt_msghdr *, size_t); static int prefixlen(const char *); static void print_getmsg(struct rt_msghdr *, int); -static void print_rtmsg(struct rt_msghdr *, int); +static void print_rtmsg(struct rt_msghdr *, size_t); static const char *routename(struct sockaddr *); static int rtmsg(int, int); static void set_metric(char *, int); @@ -1307,7 +1307,6 @@ const char *msgtypes[] = { "RTM_DELMADDR: multicast group membership removed from iface", "RTM_IFANNOUNCE: interface arrival/departure", "RTM_IEEE80211: IEEE 802.11 wireless event", - 0, }; char metricnames[] = @@ -1325,8 +1324,11 @@ char ifnetflags[] = char addrnames[] = "\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD"; +static const char errfmt[] = +"\n%s: truncated route message, only %zu bytes left\n"; + static void -print_rtmsg(struct rt_msghdr *rtm, int msglen __unused) +print_rtmsg(struct rt_msghdr *rtm, size_t msglen) { struct if_msghdr *ifm; struct ifa_msghdr *ifam; @@ -1343,13 +1345,22 @@ print_rtmsg(struct rt_msghdr *rtm, int m rtm->rtm_version); return; } - if (msgtypes[rtm->rtm_type] != NULL) + if (rtm->rtm_type < sizeof(msgtypes) / sizeof(msgtypes[0])) (void)printf("%s: ", msgtypes[rtm->rtm_type]); else - (void)printf("#%d: ", rtm->rtm_type); + (void)printf("unknown type %d: ", rtm->rtm_type); (void)printf("len %d, ", rtm->rtm_msglen); + +#define REQUIRE(x) do { \ + if (msglen < sizeof(x)) \ + goto badlen; \ + else \ + msglen -= sizeof(x); \ + } while (0) + switch (rtm->rtm_type) { case RTM_IFINFO: + REQUIRE(struct if_msghdr); ifm = (struct if_msghdr *)rtm; (void) printf("if# %d, ", ifm->ifm_index); switch (ifm->ifm_data.ifi_link_state) { @@ -1365,23 +1376,26 @@ print_rtmsg(struct rt_msghdr *rtm, int m } (void) printf("link: %s, flags:", state); bprintf(stdout, ifm->ifm_flags, ifnetflags); - pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs); + pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs, msglen); break; case RTM_NEWADDR: case RTM_DELADDR: + REQUIRE(struct ifa_msghdr); ifam = (struct ifa_msghdr *)rtm; (void) printf("metric %d, flags:", ifam->ifam_metric); bprintf(stdout, ifam->ifam_flags, routeflags); - pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs); + pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs, msglen); break; #ifdef RTM_NEWMADDR case RTM_NEWMADDR: case RTM_DELMADDR: + REQUIRE(struct ifma_msghdr); ifmam = (struct ifma_msghdr *)rtm; - pmsg_addrs((char *)(ifmam + 1), ifmam->ifmam_addrs); + pmsg_addrs((char *)(ifmam + 1), ifmam->ifmam_addrs, msglen); break; #endif case RTM_IFANNOUNCE: + REQUIRE(struct if_announcemsghdr); ifan = (struct if_announcemsghdr *)rtm; (void) printf("if# %d, what: ", ifan->ifan_index); switch (ifan->ifan_what) { @@ -1402,8 +1416,14 @@ print_rtmsg(struct rt_msghdr *rtm, int m (void) printf("pid: %ld, seq %d, errno %d, flags:", (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno); bprintf(stdout, rtm->rtm_flags, routeflags); - pmsg_common(rtm); + pmsg_common(rtm, msglen); } + + return; + +badlen: + (void)printf(errfmt, __func__, msglen); +#undef REQUIRE } static void @@ -1491,7 +1511,7 @@ print_getmsg(struct rt_msghdr *rtm, int #undef msec #define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD) if (verbose) - pmsg_common(rtm); + pmsg_common(rtm, msglen); else if (rtm->rtm_addrs &~ RTA_IGN) { (void) printf("sockaddrs: "); bprintf(stdout, rtm->rtm_addrs, addrnames); @@ -1501,17 +1521,21 @@ print_getmsg(struct rt_msghdr *rtm, int } static void -pmsg_common(struct rt_msghdr *rtm) +pmsg_common(struct rt_msghdr *rtm, size_t msglen) { (void) printf("\nlocks: "); bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames); (void) printf(" inits: "); bprintf(stdout, rtm->rtm_inits, metricnames); - pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs); + if (msglen > sizeof(struct rt_msghdr)) + pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs, + msglen - sizeof(struct rt_msghdr)); + else + (void) fflush(stdout); } static void -pmsg_addrs(char *cp, int addrs) +pmsg_addrs(char *cp, int addrs, size_t len) { struct sockaddr *sa; int i; @@ -1526,7 +1550,12 @@ pmsg_addrs(char *cp, int addrs) for (i = 1; i != 0; i <<= 1) if (i & addrs) { sa = (struct sockaddr *)cp; + if (len == 0 || len < SA_SIZE(sa)) { + (void) printf(errfmt, __func__, len); + break; + } (void) printf(" %s", routename(sa)); + len -= SA_SIZE(sa); cp += SA_SIZE(sa); } (void) putchar('\n');