summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2017-11-06 14:04:14 (GMT)
committerThomas Haller <thaller@redhat.com>2017-11-06 14:08:25 (GMT)
commit1228a65963956300bd0466437530b975e0eaeec5 (patch)
tree7c48db75762c40eb2dea1579f596aaeb56679fa2 /lib
parent56229168614a11897bd620c363e71aca3faf23ee (diff)
downloadlibnl-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.c28
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;