If a route entry is too large for the dump skb, the dump is silently truncated and no error is returned. For handlers with RTNL_FLAG_DUMP_SPLIT_NLM_DONE, rtnl_dumpit() drops -EMSGSIZE and returns skb->len. With an empty skb this is 0, so the dump ends with NLMSG_DONE and status 0, and the remaining entries are lost. The first dump skb is allocated from __netlink_dump_start() while max_recvmsg_len is still 0, so it is only NLMSG_GOODSIZE. On a 4K page kernel that is under 4000 bytes, and a 500 way multipath route does not fit: ip link add dummy0 type dummy ip link set dummy0 up ip route add 198.51.100.0/24 table 100 \ $(for i in $(seq 500); do echo -n "nexthop dev dummy0 "; done) ip route show table 100 The dump prints nothing and exits 0 Only ignore -EMSGSIZE when the skb has data, so that an entry which does not fit in an empty skb reports the error to user space. Fixes: 5b4b62a169e1 ("rtnetlink: make the "split" NLM_DONE handling generic") Signed-off-by: Stephen Hemminger --- net/core/rtnetlink.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index e141340172ce..2777796a4ed2 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -7043,7 +7043,10 @@ static int rtnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb) * Some applications which parse netlink manually depend on this. */ if (cb->flags & RTNL_FLAG_DUMP_SPLIT_NLM_DONE) { - if (err < 0 && err != -EMSGSIZE) + /* -EMSGSIZE with nothing in the skb is an error, as returning + * a length of 0 would end the dump as if it was complete. + */ + if (err < 0 && (err != -EMSGSIZE || !skb->len)) return err; if (!err) cb->data = NULL; -- 2.53.0