From: Martin Willi Date: Mon, 11 Mar 2013 11:32:21 +0000 (+0100) Subject: When adding Netlink attributes, increase header length with potential alignment X-Git-Tag: 5.0.3rc1~55^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d3f5a05e292f63ef285a1f0a458669f59bf179fc;p=thirdparty%2Fstrongswan.git When adding Netlink attributes, increase header length with potential alignment If the payload is unaligned, we must make sure the total netlink message length includes the added alignment for the first attribute. --- diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c index e81e55c241..3231f82120 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c @@ -1259,7 +1259,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_ALG_AEAD; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + enc_key.len); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1291,7 +1292,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_ALG_CRYPT; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1344,8 +1346,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_ALG_AUTH_TRUNC; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_auth) + int_key.len); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1364,8 +1366,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_ALG_AUTH; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1394,7 +1396,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, ipcomp_transform_names, ipcomp); rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1414,8 +1416,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_ENCAP; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1446,7 +1447,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1464,8 +1465,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_TFCPAD; rthdr->rta_len = RTA_LENGTH(sizeof(u_int32_t)); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1487,8 +1487,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t, rthdr->rta_type = XFRMA_REPLAY_ESN_VAL; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) + (this->replay_window + 7) / 8); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1580,7 +1580,7 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return; @@ -1681,7 +1681,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -1784,7 +1784,7 @@ METHOD(kernel_ipsec_t, del_sa, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -1828,7 +1828,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t, struct nlmsghdr *hdr, *out = NULL; struct xfrm_usersa_id *sa_id; struct xfrm_usersa_info *out_sa = NULL, *sa; - size_t len; + size_t len, newlen; struct rtattr *rta; size_t rtasize; struct xfrm_encap_tmpl* tmpl = NULL; @@ -1866,7 +1866,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -1956,8 +1956,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t, tmpl->encap_dport = ntohs(new_dst->get_port(new_dst)); } memcpy(pos, rta, rta->rta_len); - pos += RTA_ALIGN(rta->rta_len); - hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); + newlen = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len); + pos += newlen - hdr->nlmsg_len; + hdr->nlmsg_len = newlen; } rta = RTA_NEXT(rta, rtasize); } @@ -1967,8 +1968,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t, { /* add tmpl if we are enabling it */ rta->rta_type = XFRMA_ENCAP; rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); - - hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -1988,8 +1988,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t, rta->rta_type = XFRMA_REPLAY_ESN_VAL; rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) + this->replay_bmp); - - hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -2003,8 +2002,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t, { rta->rta_type = XFRMA_REPLAY_VAL; rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state)); - - hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len); if (hdr->nlmsg_len > sizeof(request)) { goto failed; @@ -2134,7 +2132,8 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this, } rthdr->rta_len += RTA_LENGTH(sizeof(struct xfrm_user_tmpl)); - hdr->nlmsg_len += RTA_ALIGN(RTA_LENGTH(sizeof(struct xfrm_user_tmpl))); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + + RTA_ALIGN(RTA_LENGTH(sizeof(struct xfrm_user_tmpl))); if (hdr->nlmsg_len > sizeof(request)) { this->mutex->unlock(this->mutex); @@ -2171,7 +2170,7 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { this->mutex->unlock(this->mutex); @@ -2414,8 +2413,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { return FAILED; @@ -2586,7 +2584,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t, rthdr->rta_type = XFRMA_MARK; rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); - hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); + hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len); if (hdr->nlmsg_len > sizeof(request)) { this->mutex->unlock(this->mutex);