Skip to content

Commit

Permalink
net: ndo_fdb_dump should report -EMSGSIZE to rtnl_fdb_dump.
Browse files Browse the repository at this point in the history
When the send skbuff reaches the end, nlmsg_put and friends returns
-EMSGSIZE but it is silently thrown away in ndo_fdb_dump. It is called
within a for_each_netdev loop and the first fdb entry of a following
netdev could fit in the remaining skbuff.  This breaks the mechanism
of cb->args[0] and idx to keep track of the entries that are already
dumped, which results missing entries in bridge fdb show command.

Signed-off-by: Minoura Makoto <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
minoura3 authored and davem330 committed Feb 26, 2016
1 parent 4c0b6ea commit 472681d
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 7 deletions.
4 changes: 3 additions & 1 deletion drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -931,8 +931,10 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
cb->nlh->nlmsg_seq,
RTM_NEWNEIGH,
NLM_F_MULTI, rd);
if (err < 0)
if (err < 0) {
cb->args[1] = err;
goto out;
}
skip:
++idx;
}
Expand Down
15 changes: 10 additions & 5 deletions net/bridge/br_fdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,8 @@ int br_fdb_dump(struct sk_buff *skb,
struct net_bridge_fdb_entry *f;

hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
int err;

if (idx < cb->args[0])
goto skip;

Expand All @@ -741,12 +743,15 @@ int br_fdb_dump(struct sk_buff *skb,
if (!filter_dev && f->dst)
goto skip;

if (fdb_fill_info(skb, br, f,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
RTM_NEWNEIGH,
NLM_F_MULTI) < 0)
err = fdb_fill_info(skb, br, f,
NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq,
RTM_NEWNEIGH,
NLM_F_MULTI);
if (err < 0) {
cb->args[1] = err;
break;
}
skip:
++idx;
}
Expand Down
6 changes: 6 additions & 0 deletions net/core/rtnetlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -2911,6 +2911,7 @@ int ndo_dflt_fdb_dump(struct sk_buff *skb,
nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->mc);
out:
netif_addr_unlock_bh(dev);
cb->args[1] = err;
return idx;
}
EXPORT_SYMBOL(ndo_dflt_fdb_dump);
Expand Down Expand Up @@ -2944,6 +2945,7 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
ops = br_dev->netdev_ops;
}

cb->args[1] = 0;
for_each_netdev(net, dev) {
if (brport_idx && (dev->ifindex != brport_idx))
continue;
Expand Down Expand Up @@ -2971,12 +2973,16 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
idx = cops->ndo_fdb_dump(skb, cb, br_dev, dev,
idx);
}
if (cb->args[1] == -EMSGSIZE)
break;

if (dev->netdev_ops->ndo_fdb_dump)
idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL,
idx);
else
idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx);
if (cb->args[1] == -EMSGSIZE)
break;

cops = NULL;
}
Expand Down
5 changes: 4 additions & 1 deletion net/switchdev/switchdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1093,8 +1093,11 @@ int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
.cb = cb,
.idx = idx,
};
int err;

switchdev_port_obj_dump(dev, &dump.fdb.obj, switchdev_port_fdb_dump_cb);
err = switchdev_port_obj_dump(dev, &dump.fdb.obj,
switchdev_port_fdb_dump_cb);
cb->args[1] = err;
return dump.idx;
}
EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump);
Expand Down

0 comments on commit 472681d

Please sign in to comment.