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,29 +1948,35 @@ static abi_long host_to_target_data_route(struct nlmsghdr *nlh)
case RTM_NEWLINK: case RTM_NEWLINK:
case RTM_DELLINK: case RTM_DELLINK:
case RTM_GETLINK: case RTM_GETLINK:
ifi = NLMSG_DATA(nlh); if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) {
ifi->ifi_type = tswap16(ifi->ifi_type); ifi = NLMSG_DATA(nlh);
ifi->ifi_index = tswap32(ifi->ifi_index); ifi->ifi_type = tswap16(ifi->ifi_type);
ifi->ifi_flags = tswap32(ifi->ifi_flags); ifi->ifi_index = tswap32(ifi->ifi_index);
ifi->ifi_change = tswap32(ifi->ifi_change); ifi->ifi_flags = tswap32(ifi->ifi_flags);
host_to_target_link_rtattr(IFLA_RTA(ifi), ifi->ifi_change = tswap32(ifi->ifi_change);
nlmsg_len - NLMSG_LENGTH(sizeof(*ifi))); host_to_target_link_rtattr(IFLA_RTA(ifi),
nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
}
break; break;
case RTM_NEWADDR: case RTM_NEWADDR:
case RTM_DELADDR: case RTM_DELADDR:
case RTM_GETADDR: case RTM_GETADDR:
ifa = NLMSG_DATA(nlh); if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifa))) {
ifa->ifa_index = tswap32(ifa->ifa_index); ifa = NLMSG_DATA(nlh);
host_to_target_addr_rtattr(IFA_RTA(ifa), ifa->ifa_index = tswap32(ifa->ifa_index);
nlmsg_len - NLMSG_LENGTH(sizeof(*ifa))); host_to_target_addr_rtattr(IFA_RTA(ifa),
nlmsg_len - NLMSG_LENGTH(sizeof(*ifa)));
}
break; break;
case RTM_NEWROUTE: case RTM_NEWROUTE:
case RTM_DELROUTE: case RTM_DELROUTE:
case RTM_GETROUTE: case RTM_GETROUTE:
rtm = NLMSG_DATA(nlh); if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*rtm))) {
rtm->rtm_flags = tswap32(rtm->rtm_flags); rtm = NLMSG_DATA(nlh);
host_to_target_route_rtattr(RTM_RTA(rtm), rtm->rtm_flags = tswap32(rtm->rtm_flags);
nlmsg_len - NLMSG_LENGTH(sizeof(*rtm))); host_to_target_route_rtattr(RTM_RTA(rtm),
nlmsg_len - NLMSG_LENGTH(sizeof(*rtm)));
}
break; break;
default: default:
return -TARGET_EINVAL; return -TARGET_EINVAL;
@ -2086,30 +2092,36 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh)
break; break;
case RTM_NEWLINK: case RTM_NEWLINK:
case RTM_DELLINK: case RTM_DELLINK:
ifi = NLMSG_DATA(nlh); if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifi))) {
ifi->ifi_type = tswap16(ifi->ifi_type); ifi = NLMSG_DATA(nlh);
ifi->ifi_index = tswap32(ifi->ifi_index); ifi->ifi_type = tswap16(ifi->ifi_type);
ifi->ifi_flags = tswap32(ifi->ifi_flags); ifi->ifi_index = tswap32(ifi->ifi_index);
ifi->ifi_change = tswap32(ifi->ifi_change); ifi->ifi_flags = tswap32(ifi->ifi_flags);
target_to_host_link_rtattr(IFLA_RTA(ifi), nlh->nlmsg_len - ifi->ifi_change = tswap32(ifi->ifi_change);
NLMSG_LENGTH(sizeof(*ifi))); target_to_host_link_rtattr(IFLA_RTA(ifi), nlh->nlmsg_len -
NLMSG_LENGTH(sizeof(*ifi)));
}
break; break;
case RTM_GETADDR: case RTM_GETADDR:
case RTM_NEWADDR: case RTM_NEWADDR:
case RTM_DELADDR: case RTM_DELADDR:
ifa = NLMSG_DATA(nlh); if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*ifa))) {
ifa->ifa_index = tswap32(ifa->ifa_index); ifa = NLMSG_DATA(nlh);
target_to_host_addr_rtattr(IFA_RTA(ifa), nlh->nlmsg_len - ifa->ifa_index = tswap32(ifa->ifa_index);
NLMSG_LENGTH(sizeof(*ifa))); target_to_host_addr_rtattr(IFA_RTA(ifa), nlh->nlmsg_len -
NLMSG_LENGTH(sizeof(*ifa)));
}
break; break;
case RTM_GETROUTE: case RTM_GETROUTE:
break; break;
case RTM_NEWROUTE: case RTM_NEWROUTE:
case RTM_DELROUTE: case RTM_DELROUTE:
rtm = NLMSG_DATA(nlh); if (nlh->nlmsg_len >= NLMSG_LENGTH(sizeof(*rtm))) {
rtm->rtm_flags = tswap32(rtm->rtm_flags); rtm = NLMSG_DATA(nlh);
target_to_host_route_rtattr(RTM_RTA(rtm), nlh->nlmsg_len - rtm->rtm_flags = tswap32(rtm->rtm_flags);
NLMSG_LENGTH(sizeof(*rtm))); target_to_host_route_rtattr(RTM_RTA(rtm), nlh->nlmsg_len -
NLMSG_LENGTH(sizeof(*rtm)));
}
break; break;
default: default:
return -TARGET_EOPNOTSUPP; return -TARGET_EOPNOTSUPP;