Re: [PATCH 1/3] rtnetlink: return EMSGSIZE when first dump entry does not fit
From: Hangbin Liu
Date: Tue Nov 10 2026 - 02:28:47 EST
On Sun, Nov 08, 2026 at 05:13:12PM -0800, Stephen Hemminger wrote:
> 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, although "ip route get
> 198.51.100.1 table 100" still shows the route.
>
> 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")
> Assisted-by: Claude:claude-opus-5-5
> Signed-off-by: Stephen Hemminger <stephen@xxxxxxxxxxxxxxxxxx>
> ---
> 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
>
Reviewed-by: Hangbin Liu <liuhangbin@xxxxxxxxxx>