From 24a7c906dc8a108732188240b117565acbb8fc92 Mon Sep 17 00:00:00 2001 From: vivek Date: Fri, 15 Apr 2016 13:32:23 -0700 Subject: [PATCH] Quagga: Fix alignment in netlink messages in some cases The alignment of nlmsg_len is calculated wrong leading to wrong rta_len calculations for nested TLVs when the data length of the last TLV added to the nested TLV is not aligned to RTA_ALIGNTO already. Use same fix that was implemented in iproute2 by Thomas Graf circa 2005. A reference to the fix is at http://oss.sgi.com/archives/netdev/2005-03/msg03103.html. Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp Ticket: CM-6491 Reviewed By: CCR-3087 Testing Done: MPLS testing with other patches in SE-1 Note: Prior to MPLS, we didn't face this problem as we haven't really had any nested TLVs; even if RTA_MULTIPATH were to be considered a nested TLV, it didn't have any non-aligned fields. --- zebra/rt_netlink.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index a6984f7f2f..41ecb1d0c4 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -1647,14 +1647,14 @@ addattr_l (struct nlmsghdr *n, unsigned int maxlen, int type, void *data, int al len = RTA_LENGTH (alen); - if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen) + if (NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len) > maxlen) return -1; rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len)); rta->rta_type = type; rta->rta_len = len; memcpy (RTA_DATA (rta), data, alen); - n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len; + n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + RTA_ALIGN (len); return 0; } @@ -1667,14 +1667,14 @@ rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen) len = RTA_LENGTH (alen); - if ((int)RTA_ALIGN (rta->rta_len) + len > maxlen) + if (RTA_ALIGN (rta->rta_len) + RTA_ALIGN (len) > maxlen) return -1; subrta = (struct rtattr *) (((char *) rta) + RTA_ALIGN (rta->rta_len)); subrta->rta_type = type; subrta->rta_len = len; memcpy (RTA_DATA (subrta), data, alen); - rta->rta_len = NLMSG_ALIGN (rta->rta_len) + len; + rta->rta_len = NLMSG_ALIGN (rta->rta_len) + RTA_ALIGN (len); return 0; } @@ -1684,21 +1684,7 @@ rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen) int addattr32 (struct nlmsghdr *n, unsigned int maxlen, int type, int data) { - int len; - struct rtattr *rta; - - len = RTA_LENGTH (4); - - if (NLMSG_ALIGN (n->nlmsg_len) + len > maxlen) - return -1; - - rta = (struct rtattr *) (((char *) n) + NLMSG_ALIGN (n->nlmsg_len)); - rta->rta_type = type; - rta->rta_len = len; - memcpy (RTA_DATA (rta), &data, 4); - n->nlmsg_len = NLMSG_ALIGN (n->nlmsg_len) + len; - - return 0; + return addattr_l(n, maxlen, type, &data, sizeof(u_int32_t)); } static int -- 2.39.5