Skip to content

Commit 7dc2bcc

Browse files
Maxim Mikityanskiydavem330
authored andcommitted
Validate required parameters in inet6_validate_link_af
inet6_set_link_af requires that at least one of IFLA_INET6_TOKEN or IFLA_INET6_ADDR_GET_MODE is passed. If none of them is passed, it returns -EINVAL, which may cause do_setlink() to fail in the middle of processing other commands and give the following warning message: A link change request failed with some changes committed already. Interface eth0 may have been left with an inconsistent configuration, please check. Check the presence of at least one of them in inet6_validate_link_af to detect invalid parameters at an early stage, before do_setlink does anything. Also validate the address generation mode at an early stage. Signed-off-by: Maxim Mikityanskiy <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 54dee40 commit 7dc2bcc

File tree

1 file changed

+35
-22
lines changed

1 file changed

+35
-22
lines changed

net/ipv6/addrconf.c

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5661,18 +5661,6 @@ static const struct nla_policy inet6_af_policy[IFLA_INET6_MAX + 1] = {
56615661
[IFLA_INET6_TOKEN] = { .len = sizeof(struct in6_addr) },
56625662
};
56635663

5664-
static int inet6_validate_link_af(const struct net_device *dev,
5665-
const struct nlattr *nla)
5666-
{
5667-
struct nlattr *tb[IFLA_INET6_MAX + 1];
5668-
5669-
if (dev && !__in6_dev_get(dev))
5670-
return -EAFNOSUPPORT;
5671-
5672-
return nla_parse_nested_deprecated(tb, IFLA_INET6_MAX, nla,
5673-
inet6_af_policy, NULL);
5674-
}
5675-
56765664
static int check_addr_gen_mode(int mode)
56775665
{
56785666
if (mode != IN6_ADDR_GEN_MODE_EUI64 &&
@@ -5693,14 +5681,44 @@ static int check_stable_privacy(struct inet6_dev *idev, struct net *net,
56935681
return 1;
56945682
}
56955683

5684+
static int inet6_validate_link_af(const struct net_device *dev,
5685+
const struct nlattr *nla)
5686+
{
5687+
struct nlattr *tb[IFLA_INET6_MAX + 1];
5688+
struct inet6_dev *idev = NULL;
5689+
int err;
5690+
5691+
if (dev) {
5692+
idev = __in6_dev_get(dev);
5693+
if (!idev)
5694+
return -EAFNOSUPPORT;
5695+
}
5696+
5697+
err = nla_parse_nested_deprecated(tb, IFLA_INET6_MAX, nla,
5698+
inet6_af_policy, NULL);
5699+
if (err)
5700+
return err;
5701+
5702+
if (!tb[IFLA_INET6_TOKEN] && !tb[IFLA_INET6_ADDR_GEN_MODE])
5703+
return -EINVAL;
5704+
5705+
if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
5706+
u8 mode = nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
5707+
5708+
if (check_addr_gen_mode(mode) < 0)
5709+
return -EINVAL;
5710+
if (dev && check_stable_privacy(idev, dev_net(dev), mode) < 0)
5711+
return -EINVAL;
5712+
}
5713+
5714+
return 0;
5715+
}
5716+
56965717
static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
56975718
{
5698-
int err = -EINVAL;
56995719
struct inet6_dev *idev = __in6_dev_get(dev);
57005720
struct nlattr *tb[IFLA_INET6_MAX + 1];
5701-
5702-
if (!idev)
5703-
return -EAFNOSUPPORT;
5721+
int err;
57045722

57055723
if (nla_parse_nested_deprecated(tb, IFLA_INET6_MAX, nla, NULL, NULL) < 0)
57065724
BUG();
@@ -5714,15 +5732,10 @@ static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
57145732
if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
57155733
u8 mode = nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
57165734

5717-
if (check_addr_gen_mode(mode) < 0 ||
5718-
check_stable_privacy(idev, dev_net(dev), mode) < 0)
5719-
return -EINVAL;
5720-
57215735
idev->cnf.addr_gen_mode = mode;
5722-
err = 0;
57235736
}
57245737

5725-
return err;
5738+
return 0;
57265739
}
57275740

57285741
static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,

0 commit comments

Comments
 (0)