Skip to content

Commit 4cb4861

Browse files
q2venPaolo Abeni
authored andcommitted
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 <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
1 parent abcec3e commit 4cb4861

File tree

1 file changed

+43
-39
lines changed

1 file changed

+43
-39
lines changed

net/ipv6/route.c

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -5051,6 +5051,44 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
50515051
[RTA_FLOWLABEL] = { .type = NLA_BE32 },
50525052
};
50535053

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+
50545092
static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
50555093
struct fib6_config *cfg,
50565094
struct netlink_ext_ack *extack)
@@ -5165,9 +5203,7 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
51655203
cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
51665204
cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
51675205

5168-
err = lwtunnel_valid_encap_type_attr(cfg->fc_mp,
5169-
cfg->fc_mp_len,
5170-
extack, true);
5206+
err = rtm_to_fib6_multipath_config(cfg, extack);
51715207
if (err < 0)
51725208
goto errout;
51735209
}
@@ -5287,19 +5323,6 @@ static bool ip6_route_mpath_should_notify(const struct fib6_info *rt)
52875323
return should_notify;
52885324
}
52895325

5290-
static int fib6_gw_from_attr(struct in6_addr *gw, struct nlattr *nla,
5291-
struct netlink_ext_ack *extack)
5292-
{
5293-
if (nla_len(nla) < sizeof(*gw)) {
5294-
NL_SET_ERR_MSG(extack, "Invalid IPv6 address in RTA_GATEWAY");
5295-
return -EINVAL;
5296-
}
5297-
5298-
*gw = nla_get_in6_addr(nla);
5299-
5300-
return 0;
5301-
}
5302-
53035326
static int ip6_route_multipath_add(struct fib6_config *cfg,
53045327
struct netlink_ext_ack *extack)
53055328
{
@@ -5340,18 +5363,11 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
53405363

53415364
nla = nla_find(attrs, attrlen, RTA_GATEWAY);
53425365
if (nla) {
5343-
err = fib6_gw_from_attr(&r_cfg.fc_gateway, nla,
5344-
extack);
5345-
if (err)
5346-
goto cleanup;
5347-
5366+
r_cfg.fc_gateway = nla_get_in6_addr(nla);
53485367
r_cfg.fc_flags |= RTF_GATEWAY;
53495368
}
5350-
r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP);
53515369

5352-
/* RTA_ENCAP_TYPE length checked in
5353-
* lwtunnel_valid_encap_type_attr
5354-
*/
5370+
r_cfg.fc_encap = nla_find(attrs, attrlen, RTA_ENCAP);
53555371
nla = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
53565372
if (nla)
53575373
r_cfg.fc_encap_type = nla_get_u16(nla);
@@ -5384,12 +5400,6 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
53845400
rtnh = rtnh_next(rtnh, &remaining);
53855401
}
53865402

5387-
if (list_empty(&rt6_nh_list)) {
5388-
NL_SET_ERR_MSG(extack,
5389-
"Invalid nexthop configuration - no valid nexthops");
5390-
return -EINVAL;
5391-
}
5392-
53935403
/* for add and replace send one notification with all nexthops.
53945404
* Skip the notification in fib6_add_rt2node and send one with
53955405
* the full route when done
@@ -5511,21 +5521,15 @@ static int ip6_route_multipath_del(struct fib6_config *cfg,
55115521

55125522
nla = nla_find(attrs, attrlen, RTA_GATEWAY);
55135523
if (nla) {
5514-
err = fib6_gw_from_attr(&r_cfg.fc_gateway, nla,
5515-
extack);
5516-
if (err) {
5517-
last_err = err;
5518-
goto next_rtnh;
5519-
}
5520-
5524+
r_cfg.fc_gateway = nla_get_in6_addr(nla);
55215525
r_cfg.fc_flags |= RTF_GATEWAY;
55225526
}
55235527
}
5528+
55245529
err = ip6_route_del(&r_cfg, extack);
55255530
if (err)
55265531
last_err = err;
55275532

5528-
next_rtnh:
55295533
rtnh = rtnh_next(rtnh, &remaining);
55305534
}
55315535

0 commit comments

Comments
 (0)