In rt6_fill_node(), when ip6mr_get_route() fails with a negative error (for example -ENODEV, -ENOENT, -ENOMEM, or -ENOBUFS), the error path currently jumps to nla_put_failure and unconditionally returns -EMSGSIZE ("RTNETLINK answers: Message too long"). Among all callers of rt6_fill_node(), only inet6_rtm_getroute() passes a non-zero iif and propagates negative errors back to userspace. Keeping -EMSGSIZE as the default return value for attribute put failures while preserving the negative error returned by ip6mr_get_route() lets userspace see the actual failure reason when multicast forwarding is enabled. This issue was pointed out during code review of rt6_fill_node() by Hangbin Liu, confirmed on a UML kernel with MRT6_INIT enabled (where "ip -6 route get ff0e::1 from 2001:db8::3 iif d0" reported "Message too long" despite the failure in ip6mr_get_route() being -ENODEV), and verified after the patch that it returns -ENODEV ("No such device") instead while other rt6_fill_node() paths behave unchanged. Built with W=1 on UML, x86_64 allmodconfig, and x86_64 allyesconfig with zero new warnings or errors. Suggested-by: Hangbin Liu Signed-off-by: Wenbo Sun --- net/ipv6/route.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6dd4a70f6490..11ce0db66484 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -5808,6 +5808,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, struct nlmsghdr *nlh; struct rtmsg *rtm; long expires = 0; + int err = -EMSGSIZE; nlh = nlmsg_put(skb, portid, seq, type, sizeof(*rtm), flags); if (!nlh) @@ -5864,12 +5865,14 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, #ifdef CONFIG_IPV6_MROUTE if (ipv6_addr_is_multicast(&rt6_dst->addr) && atomic_read(&net->ipv6.devconf_all->mc_forwarding)) { - int err = ip6mr_get_route(net, skb, rtm, portid); + int ret = ip6mr_get_route(net, skb, rtm, portid); - if (err == 0) + if (ret == 0) return 0; - if (err < 0) + if (ret < 0) { + err = ret; goto nla_put_failure; + } } else #endif if (nla_put_u32(skb, RTA_IIF, iif)) @@ -5992,7 +5995,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb, nla_put_failure: nlmsg_cancel(skb, nlh); - return -EMSGSIZE; + return err; } static int fib6_info_nh_uses_dev(struct fib6_nh *nh, void *arg) -- 2.33.0