aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorLaurent Vivier <laurent@vivier.eu>2016-06-16 21:01:37 +0200
committerRiku Voipio <riku.voipio@linaro.org>2016-06-26 13:17:22 +0300
commitb9403979b5c51d42018f40bf568d07519edb992e (patch)
treea45a797874c860e539751840dbf64fce950d1238 /linux-user
parent48dc0f2c3d87c74c31a27e1d17dabf26c378b1e8 (diff)
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>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/syscall.c72
1 files changed, 42 insertions, 30 deletions
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 4b0d791104..d3d7ee600a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1948,29 +1948,35 @@ static abi_long host_to_target_data_route(struct nlmsghdr *nlh)
case RTM_NEWLINK:
case RTM_DELLINK:
case RTM_GETLINK:
- ifi = NLMSG_DATA(nlh);
- ifi->ifi_type = tswap16(ifi->ifi_type);
- ifi->ifi_index = tswap32(ifi->ifi_index);
- ifi->ifi_flags = tswap32(ifi->ifi_flags);
- ifi->ifi_change = tswap32(ifi->ifi_change);
- host_to_target_link_rtattr(IFLA_RTA(ifi),
- nlmsg_len - NLMSG_LENGTH(sizeof(*ifi)));
+ 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);
+ ifi->ifi_flags = tswap32(ifi->ifi_flags);
+ 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:
- 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)));
+ 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:
- 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)));
+ 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,30 +2092,36 @@ static abi_long target_to_host_data_route(struct nlmsghdr *nlh)
break;
case RTM_NEWLINK:
case RTM_DELLINK:
- ifi = NLMSG_DATA(nlh);
- ifi->ifi_type = tswap16(ifi->ifi_type);
- ifi->ifi_index = tswap32(ifi->ifi_index);
- ifi->ifi_flags = tswap32(ifi->ifi_flags);
- ifi->ifi_change = tswap32(ifi->ifi_change);
- target_to_host_link_rtattr(IFLA_RTA(ifi), nlh->nlmsg_len -
- NLMSG_LENGTH(sizeof(*ifi)));
+ 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);
+ ifi->ifi_flags = tswap32(ifi->ifi_flags);
+ 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:
- 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)));
+ 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:
- 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)));
+ 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;