linux-user: don't swap NLMSG_DATA() fields

If the structure pointed by NLMSG_DATA() is bigger
than the size of NLMSG_DATA(), don't swap its fields
to avoid memory corruption.

Signed-off-by: Laurent Vivier <laurent@vivier.eu>
Signed-off-by: Riku Voipio <riku.voipio@linaro.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Laurent Vivier 2016-06-16 21:01:37 +02:00 committed by Riku Voipio
parent 48dc0f2c3d
commit b9403979b5

View File

@ -1948,6 +1948,7 @@ static abi_long host_to_target_data_route(struct nlmsghdr *nlh)
case RTM_NEWLINK:
case RTM_DELLINK:
case RTM_GETLINK:
if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) {
ifi = NLMSG_DATA(nlh);
ifi->ifi_type = tswap16(ifi->ifi_type);
ifi->ifi_index = tswap32(ifi->ifi_index);
@ -1955,22 +1956,27 @@ static abi_long host_to_target_data_route(struct nlmsghdr *nlh)
ifi->ifi_change = tswap32(ifi->ifi_change);
host_to_target_link_rtattr(IFLA_RTA(ifi),
nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
}
break;
case RTM_NEWADDR:
case RTM_DELADDR:
case RTM_GETADDR:
if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifa))) {
ifa = NLMSG_DATA(nlh);
ifa->ifa_index = tswap32(ifa->ifa_index);
host_to_target_addr_rtattr(IFA_RTA(ifa),
nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
}
break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
case RTM_GETROUTE:
if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*rtm))) {
rtm = NLMSG_DATA(nlh);
rtm->rtm_flags = tswap32(rtm->rtm_flags);
host_to_target_route_rtattr(RTM_RTA(rtm),
nlmsg_len - NLMSG_LENGTH(sizeof(*rtm)));
}
break;
default:
return -TARGET_EINVAL;
@ -2086,6 +2092,7 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh)
break;
case RTM_NEWLINK:
case RTM_DELLINK:
if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) {
ifi = NLMSG_DATA(nlh);
ifi->ifi_type = tswap16(ifi->ifi_type);
ifi->ifi_index = tswap32(ifi->ifi_index);
@ -2093,23 +2100,28 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh)
ifi->ifi_change = tswap32(ifi->ifi_change);
target_to_host_link_rtattr(IFLA_RTA(ifi), nlh->nlmsg_len -
NLMSG_LENGTH(sizeof(*ifi)));
}
break;
case RTM_GETADDR:
case RTM_NEWADDR:
case RTM_DELADDR:
if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifa))) {
ifa = NLMSG_DATA(nlh);
ifa->ifa_index = tswap32(ifa->ifa_index);
target_to_host_addr_rtattr(IFA_RTA(ifa), nlh->nlmsg_len -
NLMSG_LENGTH(sizeof(*ifa)));
}
break;
case RTM_GETROUTE:
break;
case RTM_NEWROUTE:
case RTM_DELROUTE:
if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*rtm))) {
rtm = NLMSG_DATA(nlh);
rtm->rtm_flags = tswap32(rtm->rtm_flags);
target_to_host_route_rtattr(RTM_RTA(rtm), nlh->nlmsg_len -
NLMSG_LENGTH(sizeof(*rtm)));
}
break;
default:
return -TARGET_EOPNOTSUPP;