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.
This commit is contained in:
Martin Willi
2013-03-11 12:32:21 +01:00
parent 8f727d8007
commit d3f5a05e29
@@ -1259,7 +1259,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
rthdr->rta_type = XFRMA_ALG_AEAD; rthdr->rta_type = XFRMA_ALG_AEAD;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_aead) +
enc_key.len); 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)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1291,7 +1292,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
rthdr->rta_type = XFRMA_ALG_CRYPT; rthdr->rta_type = XFRMA_ALG_CRYPT;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + enc_key.len); 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)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1344,8 +1346,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
rthdr->rta_type = XFRMA_ALG_AUTH_TRUNC; rthdr->rta_type = XFRMA_ALG_AUTH_TRUNC;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_auth) + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo_auth) +
int_key.len); int_key.len);
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1364,8 +1366,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
rthdr->rta_type = XFRMA_ALG_AUTH; rthdr->rta_type = XFRMA_ALG_AUTH;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len); rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo) + int_key.len);
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1394,7 +1396,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
ipcomp_transform_names, ipcomp); ipcomp_transform_names, ipcomp);
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_algo)); 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)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1414,8 +1416,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
rthdr->rta_type = XFRMA_ENCAP; rthdr->rta_type = XFRMA_ENCAP;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1446,7 +1447,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
rthdr->rta_type = XFRMA_MARK; rthdr->rta_type = XFRMA_MARK;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_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)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1464,8 +1465,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
rthdr->rta_type = XFRMA_TFCPAD; rthdr->rta_type = XFRMA_TFCPAD;
rthdr->rta_len = RTA_LENGTH(sizeof(u_int32_t)); rthdr->rta_len = RTA_LENGTH(sizeof(u_int32_t));
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1487,8 +1487,8 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
rthdr->rta_type = XFRMA_REPLAY_ESN_VAL; rthdr->rta_type = XFRMA_REPLAY_ESN_VAL;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) + rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) +
(this->replay_window + 7) / 8); (this->replay_window + 7) / 8);
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) +
hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len); RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1580,7 +1580,7 @@ static void get_replay_state(private_kernel_netlink_ipsec_t *this,
rthdr->rta_type = XFRMA_MARK; rthdr->rta_type = XFRMA_MARK;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_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)) if (hdr->nlmsg_len > sizeof(request))
{ {
return; return;
@@ -1681,7 +1681,7 @@ METHOD(kernel_ipsec_t, query_sa, status_t,
rthdr->rta_type = XFRMA_MARK; rthdr->rta_type = XFRMA_MARK;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_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)) if (hdr->nlmsg_len > sizeof(request))
{ {
return FAILED; return FAILED;
@@ -1784,7 +1784,7 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
rthdr->rta_type = XFRMA_MARK; rthdr->rta_type = XFRMA_MARK;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_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)) if (hdr->nlmsg_len > sizeof(request))
{ {
return FAILED; return FAILED;
@@ -1828,7 +1828,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
struct nlmsghdr *hdr, *out = NULL; struct nlmsghdr *hdr, *out = NULL;
struct xfrm_usersa_id *sa_id; struct xfrm_usersa_id *sa_id;
struct xfrm_usersa_info *out_sa = NULL, *sa; struct xfrm_usersa_info *out_sa = NULL, *sa;
size_t len; size_t len, newlen;
struct rtattr *rta; struct rtattr *rta;
size_t rtasize; size_t rtasize;
struct xfrm_encap_tmpl* tmpl = NULL; 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_type = XFRMA_MARK;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_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)) if (hdr->nlmsg_len > sizeof(request))
{ {
return FAILED; return FAILED;
@@ -1956,8 +1956,9 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
tmpl->encap_dport = ntohs(new_dst->get_port(new_dst)); tmpl->encap_dport = ntohs(new_dst->get_port(new_dst));
} }
memcpy(pos, rta, rta->rta_len); memcpy(pos, rta, rta->rta_len);
pos += RTA_ALIGN(rta->rta_len); newlen = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len);
hdr->nlmsg_len += RTA_ALIGN(rta->rta_len); pos += newlen - hdr->nlmsg_len;
hdr->nlmsg_len = newlen;
} }
rta = RTA_NEXT(rta, rtasize); rta = RTA_NEXT(rta, rtasize);
} }
@@ -1967,8 +1968,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
{ /* add tmpl if we are enabling it */ { /* add tmpl if we are enabling it */
rta->rta_type = XFRMA_ENCAP; rta->rta_type = XFRMA_ENCAP;
rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl)); rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_encap_tmpl));
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len);
hdr->nlmsg_len += RTA_ALIGN(rta->rta_len);
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -1988,8 +1988,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
rta->rta_type = XFRMA_REPLAY_ESN_VAL; rta->rta_type = XFRMA_REPLAY_ESN_VAL;
rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) + rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state_esn) +
this->replay_bmp); this->replay_bmp);
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len);
hdr->nlmsg_len += RTA_ALIGN(rta->rta_len);
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; goto failed;
@@ -2003,8 +2002,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
{ {
rta->rta_type = XFRMA_REPLAY_VAL; rta->rta_type = XFRMA_REPLAY_VAL;
rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state)); rta->rta_len = RTA_LENGTH(sizeof(struct xfrm_replay_state));
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rta->rta_len);
hdr->nlmsg_len += RTA_ALIGN(rta->rta_len);
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
goto failed; 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)); 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)) if (hdr->nlmsg_len > sizeof(request))
{ {
this->mutex->unlock(this->mutex); 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_type = XFRMA_MARK;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_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)) if (hdr->nlmsg_len > sizeof(request))
{ {
this->mutex->unlock(this->mutex); this->mutex->unlock(this->mutex);
@@ -2414,8 +2413,7 @@ METHOD(kernel_ipsec_t, query_policy, status_t,
rthdr->rta_type = XFRMA_MARK; rthdr->rta_type = XFRMA_MARK;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark)); rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_mark));
hdr->nlmsg_len = NLMSG_ALIGN(hdr->nlmsg_len) + RTA_ALIGN(rthdr->rta_len);
hdr->nlmsg_len += RTA_ALIGN(rthdr->rta_len);
if (hdr->nlmsg_len > sizeof(request)) if (hdr->nlmsg_len > sizeof(request))
{ {
return FAILED; return FAILED;
@@ -2586,7 +2584,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
rthdr->rta_type = XFRMA_MARK; rthdr->rta_type = XFRMA_MARK;
rthdr->rta_len = RTA_LENGTH(sizeof(struct xfrm_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)) if (hdr->nlmsg_len > sizeof(request))
{ {
this->mutex->unlock(this->mutex); this->mutex->unlock(this->mutex);