diff options
author | Thomas Haller <thaller@redhat.com> | 2017-11-06 14:04:14 (GMT) |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-11-06 14:08:25 (GMT) |
commit | 1228a65963956300bd0466437530b975e0eaeec5 (patch) | |
tree | 7c48db75762c40eb2dea1579f596aaeb56679fa2 /lib | |
parent | 56229168614a11897bd620c363e71aca3faf23ee (diff) | |
download | libnl-1228a65963956300bd0466437530b975e0eaeec5.zip libnl-1228a65963956300bd0466437530b975e0eaeec5.tar.gz libnl-1228a65963956300bd0466437530b975e0eaeec5.tar.bz2 |
route: fix handling old_nh in rtnl_route_parse() and avoid leak
The previous code would miss to release old_nh in the error
path.
Also, it relied on the present netlink attributes to have old_nh
initialized. Don't do that.
Also, fixup error codes by using "goto errout_nomem" where appropriate
and keep @err as returned from rtnl_route_set_metric().
Diffstat (limited to 'lib')
-rw-r--r-- | lib/route/route_obj.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c index 8ae6b89..bc62408 100644 --- a/lib/route/route_obj.c +++ b/lib/route/route_obj.c @@ -1125,10 +1125,8 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) int err, family; route = rtnl_route_alloc(); - if (!route) { - err = -NLE_NOMEM; - goto errout; - } + if (!route) + goto errout_nomem; route->ce_msgtype = nlh->nlmsg_type; @@ -1213,7 +1211,9 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) for (i = 1; i <= RTAX_MAX; i++) { if (mtb[i] && nla_len(mtb[i]) >= sizeof(uint32_t)) { uint32_t m = nla_get_u32(mtb[i]); - if (rtnl_route_set_metric(route, i, m) < 0) + + err = rtnl_route_set_metric(route, i, m); + if (err < 0) goto errout; } } @@ -1231,14 +1231,14 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) if (tb[RTA_OIF]) { if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) - goto errout; + goto errout_nomem; rtnl_route_nh_set_ifindex(old_nh, nla_get_u32(tb[RTA_OIF])); } if (tb[RTA_GATEWAY]) { if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) - goto errout; + goto errout_nomem; if (!(addr = nl_addr_alloc_attr(tb[RTA_GATEWAY], family))) goto errout_nomem; @@ -1249,7 +1249,7 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) if (tb[RTA_FLOW]) { if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) - goto errout; + goto errout_nomem; rtnl_route_nh_set_realms(old_nh, nla_get_u32(tb[RTA_FLOW])); } @@ -1257,6 +1257,9 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) if (tb[RTA_NEWDST]) { struct nl_addr *addr; + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) + goto errout_nomem; + addr = nl_addr_alloc_attr(tb[RTA_NEWDST], route->rt_family); if (!addr) goto errout_nomem; @@ -1271,6 +1274,9 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) int alen = nla_len(tb[RTA_VIA]) - offsetof(struct rtvia, rtvia_addr); struct rtvia *via = nla_data(tb[RTA_VIA]); + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) + goto errout_nomem; + addr = nl_addr_build(via->rtvia_family, via->rtvia_addr, alen); if (!addr) goto errout_nomem; @@ -1287,6 +1293,9 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) } if (tb[RTA_ENCAP] && tb[RTA_ENCAP_TYPE]) { + if (!old_nh && !(old_nh = rtnl_route_nh_alloc())) + goto errout_nomem; + err = nh_encap_parse_msg(tb[RTA_ENCAP], tb[RTA_ENCAP_TYPE], old_nh); if (err) @@ -1319,12 +1328,15 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result) rtnl_route_nh_free(old_nh); } + old_nh = NULL; } *result = route; return 0; errout: + if (old_nh) + rtnl_route_nh_free(old_nh); rtnl_route_put(route); return err; |