Commit 472681d5 authored by MINOURA Makoto / 箕浦 真's avatar MINOURA Makoto / 箕浦 真 Committed by David S. Miller

net: ndo_fdb_dump should report -EMSGSIZE to rtnl_fdb_dump.

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: default avatarMinoura Makoto <minoura@valinux.co.jp>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4c0b6eaf
...@@ -931,8 +931,10 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, ...@@ -931,8 +931,10 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
RTM_NEWNEIGH, RTM_NEWNEIGH,
NLM_F_MULTI, rd); NLM_F_MULTI, rd);
if (err < 0) if (err < 0) {
cb->args[1] = err;
goto out; goto out;
}
skip: skip:
++idx; ++idx;
} }
......
...@@ -723,6 +723,8 @@ int br_fdb_dump(struct sk_buff *skb, ...@@ -723,6 +723,8 @@ int br_fdb_dump(struct sk_buff *skb,
struct net_bridge_fdb_entry *f; struct net_bridge_fdb_entry *f;
hlist_for_each_entry_rcu(f, &br->hash[i], hlist) { hlist_for_each_entry_rcu(f, &br->hash[i], hlist) {
int err;
if (idx < cb->args[0]) if (idx < cb->args[0])
goto skip; goto skip;
...@@ -741,12 +743,15 @@ int br_fdb_dump(struct sk_buff *skb, ...@@ -741,12 +743,15 @@ int br_fdb_dump(struct sk_buff *skb,
if (!filter_dev && f->dst) if (!filter_dev && f->dst)
goto skip; goto skip;
if (fdb_fill_info(skb, br, f, err = fdb_fill_info(skb, br, f,
NETLINK_CB(cb->skb).portid, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, cb->nlh->nlmsg_seq,
RTM_NEWNEIGH, RTM_NEWNEIGH,
NLM_F_MULTI) < 0) NLM_F_MULTI);
if (err < 0) {
cb->args[1] = err;
break; break;
}
skip: skip:
++idx; ++idx;
} }
......
...@@ -2911,6 +2911,7 @@ int ndo_dflt_fdb_dump(struct sk_buff *skb, ...@@ -2911,6 +2911,7 @@ int ndo_dflt_fdb_dump(struct sk_buff *skb,
nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->mc); nlmsg_populate_fdb(skb, cb, dev, &idx, &dev->mc);
out: out:
netif_addr_unlock_bh(dev); netif_addr_unlock_bh(dev);
cb->args[1] = err;
return idx; return idx;
} }
EXPORT_SYMBOL(ndo_dflt_fdb_dump); EXPORT_SYMBOL(ndo_dflt_fdb_dump);
...@@ -2944,6 +2945,7 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2944,6 +2945,7 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
ops = br_dev->netdev_ops; ops = br_dev->netdev_ops;
} }
cb->args[1] = 0;
for_each_netdev(net, dev) { for_each_netdev(net, dev) {
if (brport_idx && (dev->ifindex != brport_idx)) if (brport_idx && (dev->ifindex != brport_idx))
continue; continue;
...@@ -2971,12 +2973,16 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -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 = cops->ndo_fdb_dump(skb, cb, br_dev, dev,
idx); idx);
} }
if (cb->args[1] == -EMSGSIZE)
break;
if (dev->netdev_ops->ndo_fdb_dump) if (dev->netdev_ops->ndo_fdb_dump)
idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL, idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL,
idx); idx);
else else
idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx); idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx);
if (cb->args[1] == -EMSGSIZE)
break;
cops = NULL; cops = NULL;
} }
......
...@@ -1093,8 +1093,11 @@ int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, ...@@ -1093,8 +1093,11 @@ int switchdev_port_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
.cb = cb, .cb = cb,
.idx = idx, .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; return dump.idx;
} }
EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump); EXPORT_SYMBOL_GPL(switchdev_port_fdb_dump);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment