Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipv6: Validate RTA_GATEWAY of RTA_MULTIPATH in rtm_to_fib6_config().

We will perform RTM_NEWROUTE and RTM_DELROUTE under RCU, and then
we want to perform some validation out of the RCU scope.

When creating / removing an IPv6 route with RTA_MULTIPATH,
inet6_rtm_newroute() / inet6_rtm_delroute() validates RTA_GATEWAY
in each multipath entry.

Let's do that in rtm_to_fib6_config().

Note that now RTM_DELROUTE returns an error for RTA_MULTIPATH with
0 entries, which was accepted but should result in -EINVAL as
RTM_NEWROUTE.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250418000443.43734-2-kuniyu@amazon.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Kuniyuki Iwashima and committed by
Paolo Abeni
4cb4861d abcec3ed

+43 -39
+43 -39
net/ipv6/route.c
··· 5051 5051 [RTA_FLOWLABEL] = { .type = NLA_BE32 }, 5052 5052 }; 5053 5053 5054 + static int rtm_to_fib6_multipath_config(struct fib6_config *cfg, 5055 + struct netlink_ext_ack *extack) 5056 + { 5057 + struct rtnexthop *rtnh; 5058 + int remaining; 5059 + 5060 + remaining = cfg->fc_mp_len; 5061 + rtnh = (struct rtnexthop *)cfg->fc_mp; 5062 + 5063 + if (!rtnh_ok(rtnh, remaining)) { 5064 + NL_SET_ERR_MSG(extack, "Invalid nexthop configuration - no valid nexthops"); 5065 + return -EINVAL; 5066 + } 5067 + 5068 + do { 5069 + int attrlen = rtnh_attrlen(rtnh); 5070 + 5071 + if (attrlen > 0) { 5072 + struct nlattr *nla, *attrs; 5073 + 5074 + attrs = rtnh_attrs(rtnh); 5075 + nla = nla_find(attrs, attrlen, RTA_GATEWAY); 5076 + if (nla) { 5077 + if (nla_len(nla) < sizeof(cfg->fc_gateway)) { 5078 + NL_SET_ERR_MSG(extack, 5079 + "Invalid IPv6 address in RTA_GATEWAY"); 5080 + return -EINVAL; 5081 + } 5082 + } 5083 + } 5084 + 5085 + rtnh = rtnh_next(rtnh, &remaining); 5086 + } while (rtnh_ok(rtnh, remaining)); 5087 + 5088 + return lwtunnel_valid_encap_type_attr(cfg->fc_mp, cfg->fc_mp_len, 5089 + extack, true); 5090 + } 5091 + 5054 5092 static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, 5055 5093 struct fib6_config *cfg, 5056 5094 struct netlink_ext_ack *extack) ··· 5203 5165 cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]); 5204 5166 cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]); 5205 5167 5206 - err = lwtunnel_valid_encap_type_attr(cfg->fc_mp, 5207 - cfg->fc_mp_len, 5208 - extack, true); 5168 + err = rtm_to_fib6_multipath_config(cfg, extack); 5209 5169 if (err < 0) 5210 5170 goto errout; 5211 5171 } ··· 5323 5287 return should_notify; 5324 5288 } 5325 5289 5326 - static int fib6_gw_from_attr(struct in6_addr *gw, struct nlattr *nla, 5327 - struct netlink_ext_ack *extack) 5328 - { 5329 - if (nla_len(nla) < sizeof(*gw)) { 5330 - NL_SET_ERR_MSG(extack, "Invalid IPv6 address in RTA_GATEWAY"); 5331 - return -EINVAL; 5332 - } 5333 - 5334 - *gw = nla_get_in6_addr(nla); 5335 - 5336 - return 0; 5337 - } 5338 - 5339 5290 static int ip6_route_multipath_add(struct fib6_config *cfg, 5340 5291 struct netlink_ext_ack *extack) 5341 5292 { ··· 5363 5340 5364 5341 nla = nla_find(attrs, attrlen, RTA_GATEWAY); 5365 5342 if (nla) { 5366 - err = fib6_gw_from_attr(&r_cfg.fc_gateway, nla, 5367 - extack); 5368 - if (err) 5369 - goto cleanup; 5370 - 5343 + r_cfg.fc_gateway = nla_get_in6_addr(nla); 5371 5344 r_cfg.fc_flags |= RTF_GATEWAY; 5372 5345 } 5373 - r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP); 5374 5346 5375 - /* RTA_ENCAP_TYPE length checked in 5376 - * lwtunnel_valid_encap_type_attr 5377 - */ 5347 + r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP); 5378 5348 nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE); 5379 5349 if (nla) 5380 5350 r_cfg.fc_encap_type = nla_get_u16(nla); ··· 5398 5382 } 5399 5383 5400 5384 rtnh = rtnh_next(rtnh, &remaining); 5401 - } 5402 - 5403 - if (list_empty(&rt6_nh_list)) { 5404 - NL_SET_ERR_MSG(extack, 5405 - "Invalid nexthop configuration - no valid nexthops"); 5406 - return -EINVAL; 5407 5385 } 5408 5386 5409 5387 /* for add and replace send one notification with all nexthops. ··· 5521 5511 5522 5512 nla = nla_find(attrs, attrlen, RTA_GATEWAY); 5523 5513 if (nla) { 5524 - err = fib6_gw_from_attr(&r_cfg.fc_gateway, nla, 5525 - extack); 5526 - if (err) { 5527 - last_err = err; 5528 - goto next_rtnh; 5529 - } 5530 - 5514 + r_cfg.fc_gateway = nla_get_in6_addr(nla); 5531 5515 r_cfg.fc_flags |= RTF_GATEWAY; 5532 5516 } 5533 5517 } 5518 + 5534 5519 err = ip6_route_del(&r_cfg, extack); 5535 5520 if (err) 5536 5521 last_err = err; 5537 5522 5538 - next_rtnh: 5539 5523 rtnh = rtnh_next(rtnh, &remaining); 5540 5524 } 5541 5525