diff options
author | Martin Willi <martin@revosec.ch> | 2013-03-11 12:32:21 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2013-03-11 12:32:21 +0100 |
commit | d3f5a05e292f63ef285a1f0a458669f59bf179fc (patch) | |
tree | 93e33d741ad66fb9d8e50579a105e94aa52f5357 | |
parent | 8f727d8007510839a17796b53afe090a8955e23d (diff) | |
download | strongswan-d3f5a05e292f63ef285a1f0a458669f59bf179fc.tar.bz2 strongswan-d3f5a05e292f63ef285a1f0a458669f59bf179fc.tar.xz |
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.
-rw-r--r-- | src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c | 62 |
1 files changed, 30 insertions, 32 deletions
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); |