Skip to content

Commit 41b4bd9

Browse files
qsndavem330
authored andcommitted
net: don't return invalid table id error when we fall back to PF_UNSPEC
In case we can't find a ->dumpit callback for the requested (family,type) pair, we fall back to (PF_UNSPEC,type). In effect, we're in the same situation as if userspace had requested a PF_UNSPEC dump. For RTM_GETROUTE, that handler is rtnl_dump_all, which calls all the registered RTM_GETROUTE handlers. The requested table id may or may not exist for all of those families. commit ae677bb ("net: Don't return invalid table id error when dumping all families") fixed the problem when userspace explicitly requests a PF_UNSPEC dump, but missed the fallback case. For example, when we pass ipv6.disable=1 to a kernel with CONFIG_IP_MROUTE=y and CONFIG_IP_MROUTE_MULTIPLE_TABLES=y, the (PF_INET6, RTM_GETROUTE) handler isn't registered, so we end up in rtnl_dump_all, and listing IPv6 routes will unexpectedly print: # ip -6 r Error: ipv4: MR table does not exist. Dump terminated commit ae677bb introduced the dump_all_families variable, which gets set when userspace requests a PF_UNSPEC dump. However, we can't simply set the family to PF_UNSPEC in rtnetlink_rcv_msg in the fallback case to get dump_all_families == true, because some messages types (for example RTM_GETRULE and RTM_GETNEIGH) only register the PF_UNSPEC handler and use the family to filter in the kernel what is dumped to userspace. We would then export more entries, that userspace would have to filter. iproute does that, but other programs may not. Instead, this patch removes dump_all_families and updates the RTM_GETROUTE handlers to check if the family that is being dumped is their own. When it's not, which covers both the intentional PF_UNSPEC dumps (as dump_all_families did) and the fallback case, ignore the missing table id error. Fixes: cb16789 ("net: Plumb support for filtering ipv4 and ipv6 multicast route dumps") Signed-off-by: Sabrina Dubroca <[email protected]> Reviewed-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 57ebc8f commit 41b4bd9

File tree

5 files changed

+4
-6
lines changed

5 files changed

+4
-6
lines changed

include/net/ip_fib.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,6 @@ struct fib_dump_filter {
257257
u32 table_id;
258258
/* filter_set is an optimization that an entry is set */
259259
bool filter_set;
260-
bool dump_all_families;
261260
bool dump_routes;
262261
bool dump_exceptions;
263262
unsigned char protocol;

net/ipv4/fib_frontend.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,6 @@ int ip_valid_fib_dump_req(struct net *net, const struct nlmsghdr *nlh,
918918
else
919919
filter->dump_exceptions = false;
920920

921-
filter->dump_all_families = (rtm->rtm_family == AF_UNSPEC);
922921
filter->flags = rtm->rtm_flags;
923922
filter->protocol = rtm->rtm_protocol;
924923
filter->rt_type = rtm->rtm_type;
@@ -990,7 +989,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
990989
if (filter.table_id) {
991990
tb = fib_get_table(net, filter.table_id);
992991
if (!tb) {
993-
if (filter.dump_all_families)
992+
if (rtnl_msg_family(cb->nlh) != PF_INET)
994993
return skb->len;
995994

996995
NL_SET_ERR_MSG(cb->extack, "ipv4: FIB table does not exist");

net/ipv4/ipmr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2613,7 +2613,7 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
26132613

26142614
mrt = ipmr_get_table(sock_net(skb->sk), filter.table_id);
26152615
if (!mrt) {
2616-
if (filter.dump_all_families)
2616+
if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IPMR)
26172617
return skb->len;
26182618

26192619
NL_SET_ERR_MSG(cb->extack, "ipv4: MR table does not exist");

net/ipv6/ip6_fib.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
664664
if (arg.filter.table_id) {
665665
tb = fib6_get_table(net, arg.filter.table_id);
666666
if (!tb) {
667-
if (arg.filter.dump_all_families)
667+
if (rtnl_msg_family(cb->nlh) != PF_INET6)
668668
goto out;
669669

670670
NL_SET_ERR_MSG_MOD(cb->extack, "FIB table does not exist");

net/ipv6/ip6mr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2503,7 +2503,7 @@ static int ip6mr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
25032503

25042504
mrt = ip6mr_get_table(sock_net(skb->sk), filter.table_id);
25052505
if (!mrt) {
2506-
if (filter.dump_all_families)
2506+
if (rtnl_msg_family(cb->nlh) != RTNL_FAMILY_IP6MR)
25072507
return skb->len;
25082508

25092509
NL_SET_ERR_MSG_MOD(cb->extack, "MR table does not exist");

0 commit comments

Comments
 (0)