aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-10-24 14:06:26 -0700
committerDavid S. Miller <davem@davemloft.net>2018-10-24 14:06:26 -0700
commit559bf69e3c8f8892c3205417c01cdf8d7823d03c (patch)
tree6664d41461603de1ddaf5024da60e3d4cfa2a8b5 /net/ipv4
parentMerge tag 'docs-4.20' of git://git.lwn.net/linux (diff)
parentnet: rtnl_dump_all needs to propagate error from dumpit function (diff)
downloadlinux-dev-559bf69e3c8f8892c3205417c01cdf8d7823d03c.tar.xz
linux-dev-559bf69e3c8f8892c3205417c01cdf8d7823d03c.zip
Merge branch 'route-dump-filter-fixes'
David Ahern says: ==================== net: Fixups for recent dump filtering changes Li RongQing noted that tgt_net is leaked in ipv4 due to the recent change to handle address dumps for a specific device. The report also applies to ipv6 and other error paths. Patches 1 and 2 fix those leaks. Patch 3 stops route dumps from erroring out when dumping across address families and a table id is given. This is needed in preparation for patch 4. Patch 4 updates the rtnl_dump_all to handle a failure in one of the dumpit functions. At the moment, if an address dump returns an error the dump all loop breaks but the error is dropped. The result can be no data is returned and no error either leaving the user wondering about the addresses. Patches were tested with a modified iproute2 to add invalid data to the dump request causing each specific failure path to be hit in addition to positive testing that it works as it should when given valid data. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/devinet.c13
-rw-r--r--net/ipv4/fib_frontend.c4
-rw-r--r--net/ipv4/ipmr.c3
3 files changed, 15 insertions, 5 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 63d5b58fbfdb..9250b309c742 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1761,7 +1761,7 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
struct net_device *dev;
struct in_device *in_dev;
struct hlist_head *head;
- int err;
+ int err = 0;
s_h = cb->args[0];
s_idx = idx = cb->args[1];
@@ -1771,12 +1771,15 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
err = inet_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net,
skb->sk, cb);
if (err < 0)
- return err;
+ goto put_tgt_net;
+ err = 0;
if (fillargs.ifindex) {
dev = __dev_get_by_index(tgt_net, fillargs.ifindex);
- if (!dev)
- return -ENODEV;
+ if (!dev) {
+ err = -ENODEV;
+ goto put_tgt_net;
+ }
in_dev = __in_dev_get_rtnl(dev);
if (in_dev) {
@@ -1821,7 +1824,7 @@ put_tgt_net:
if (fillargs.netnsid >= 0)
put_net(tgt_net);
- return skb->len;
+ return err < 0 ? err : skb->len;
}
static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh,
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c
index 5bf653f36911..6df95be96311 100644
--- a/net/ipv4/fib_frontend.c
+++ b/net/ipv4/fib_frontend.c
@@ -829,6 +829,7 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
return -EINVAL;
}
+ filter->dump_all_families = (rtm->rtm_family == AF_UNSPEC);
filter->flags = rtm->rtm_flags;
filter->protocol = rtm->rtm_protocol;
filter->rt_type = rtm->rtm_type;
@@ -899,6 +900,9 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
if (filter.table_id) {
tb = fib_get_table(net, filter.table_id);
if (!tb) {
+ if (filter.dump_all_families)
+ return skb->len;
+
NL_SET_ERR_MSG(cb->extack, "ipv4: FIB table does not exist");
return -ENOENT;
}
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index 7a3e2acda94c..a6defbec4f1b 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -2542,6 +2542,9 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
mrt = ipmr_get_table(sock_net(skb->sk), filter.table_id);
if (!mrt) {
+ if (filter.dump_all_families)
+ return skb->len;
+
NL_SET_ERR_MSG(cb->extack, "ipv4: MR table does not exist");
return -ENOENT;
}