Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -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;
			}
+10 −5
Original line number Diff line number Diff line
@@ -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;

@@ -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,
			err = fdb_fill_info(skb, br, f,
					    NETLINK_CB(cb->skb).portid,
					    cb->nlh->nlmsg_seq,
					    RTM_NEWNEIGH,
					  NLM_F_MULTI) < 0)
					    NLM_F_MULTI);
			if (err < 0) {
				cb->args[1] = err;
				break;
			}
skip:
			++idx;
		}
+6 −0
Original line number Diff line number Diff line
@@ -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);
@@ -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;
@@ -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;
	}
+4 −1
Original line number Diff line number Diff line
@@ -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);