From d3f5a05e292f63ef285a1f0a458669f59bf179fc Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Mon, 11 Mar 2013 12:32:21 +0100 Subject: 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. --- .../plugins/kernel_netlink/kernel_netlink_ipsec.c | 62 +++++++++++----------- 1 file changed, 30 insertions(+), 32 deletions(-) (limited to 'src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c') diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c index e81e55c24..3231f8212 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); -- cgit v1.2.3