Merge branch 'rtnetlink-improve-alt_ifname-config-and-fix-dangerous-group-usage'
Florent Fourcot says: ==================== rtnetlink: improve ALT_IFNAME config and fix dangerous GROUP usage First commit forbids dangerous calls when both IFNAME and GROUP are given, since it can introduce unexpected behaviour when IFNAME does not match any interface. Second patch achieves primary goal of this patchset to fix/improve IFLA_ALT_IFNAME attribute, since previous code was never working for newlink/setlink. ip-link command is probably getting interface index before, and was not using this feature. Last two patches are improving error code on corner cases. Changes in v2: * Remove ifname argument in rtnl_dev_get/do_setlink functions (simplify code) * Use a boolean to avoid condition duplication in __rtnl_newlink Changes in v3: * Simplify rtnl_dev_get signature Changes in v4: * Rename link_lookup to link_specified Changes in v5: * Re-order patches ==================== Link: https://lore.kernel.org/r/20220415165330.10497-1-florent.fourcot@wifirst.fr Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
cc4bdef26e
|
@ -2644,17 +2644,23 @@ static int do_set_proto_down(struct net_device *dev,
|
|||
static int do_setlink(const struct sk_buff *skb,
|
||||
struct net_device *dev, struct ifinfomsg *ifm,
|
||||
struct netlink_ext_ack *extack,
|
||||
struct nlattr **tb, char *ifname, int status)
|
||||
struct nlattr **tb, int status)
|
||||
{
|
||||
const struct net_device_ops *ops = dev->netdev_ops;
|
||||
char ifname[IFNAMSIZ];
|
||||
int err;
|
||||
|
||||
err = validate_linkmsg(dev, tb, extack);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[IFLA_IFNAME])
|
||||
nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
|
||||
else
|
||||
ifname[0] = '\0';
|
||||
|
||||
if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD] || tb[IFLA_TARGET_NETNSID]) {
|
||||
const char *pat = ifname && ifname[0] ? ifname : NULL;
|
||||
const char *pat = ifname[0] ? ifname : NULL;
|
||||
struct net *net;
|
||||
int new_ifindex;
|
||||
|
||||
|
@ -3010,21 +3016,16 @@ errout:
|
|||
}
|
||||
|
||||
static struct net_device *rtnl_dev_get(struct net *net,
|
||||
struct nlattr *ifname_attr,
|
||||
struct nlattr *altifname_attr,
|
||||
char *ifname)
|
||||
struct nlattr *tb[])
|
||||
{
|
||||
char buffer[ALTIFNAMSIZ];
|
||||
char ifname[ALTIFNAMSIZ];
|
||||
|
||||
if (!ifname) {
|
||||
ifname = buffer;
|
||||
if (ifname_attr)
|
||||
nla_strscpy(ifname, ifname_attr, IFNAMSIZ);
|
||||
else if (altifname_attr)
|
||||
nla_strscpy(ifname, altifname_attr, ALTIFNAMSIZ);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
if (tb[IFLA_IFNAME])
|
||||
nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
|
||||
else if (tb[IFLA_ALT_IFNAME])
|
||||
nla_strscpy(ifname, tb[IFLA_ALT_IFNAME], ALTIFNAMSIZ);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
return __dev_get_by_name(net, ifname);
|
||||
}
|
||||
|
@ -3037,7 +3038,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
struct net_device *dev;
|
||||
int err;
|
||||
struct nlattr *tb[IFLA_MAX+1];
|
||||
char ifname[IFNAMSIZ];
|
||||
|
||||
err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFLA_MAX,
|
||||
ifla_policy, extack);
|
||||
|
@ -3048,17 +3048,12 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
if (tb[IFLA_IFNAME])
|
||||
nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
|
||||
else
|
||||
ifname[0] = '\0';
|
||||
|
||||
err = -EINVAL;
|
||||
ifm = nlmsg_data(nlh);
|
||||
if (ifm->ifi_index > 0)
|
||||
dev = __dev_get_by_index(net, ifm->ifi_index);
|
||||
else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
|
||||
dev = rtnl_dev_get(net, NULL, tb[IFLA_ALT_IFNAME], ifname);
|
||||
dev = rtnl_dev_get(net, tb);
|
||||
else
|
||||
goto errout;
|
||||
|
||||
|
@ -3067,7 +3062,7 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
goto errout;
|
||||
}
|
||||
|
||||
err = do_setlink(skb, dev, ifm, extack, tb, ifname, 0);
|
||||
err = do_setlink(skb, dev, ifm, extack, tb, 0);
|
||||
errout:
|
||||
return err;
|
||||
}
|
||||
|
@ -3156,15 +3151,14 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (ifm->ifi_index > 0)
|
||||
dev = __dev_get_by_index(tgt_net, ifm->ifi_index);
|
||||
else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
|
||||
dev = rtnl_dev_get(net, tb[IFLA_IFNAME],
|
||||
tb[IFLA_ALT_IFNAME], NULL);
|
||||
dev = rtnl_dev_get(net, tb);
|
||||
else if (tb[IFLA_GROUP])
|
||||
err = rtnl_group_dellink(tgt_net, nla_get_u32(tb[IFLA_GROUP]));
|
||||
else
|
||||
goto out;
|
||||
|
||||
if (!dev) {
|
||||
if (tb[IFLA_IFNAME] || ifm->ifi_index > 0)
|
||||
if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME] || ifm->ifi_index > 0)
|
||||
err = -ENODEV;
|
||||
|
||||
goto out;
|
||||
|
@ -3299,7 +3293,7 @@ static int rtnl_group_changelink(const struct sk_buff *skb,
|
|||
|
||||
for_each_netdev_safe(net, dev, aux) {
|
||||
if (dev->group == group) {
|
||||
err = do_setlink(skb, dev, ifm, extack, tb, NULL, 0);
|
||||
err = do_setlink(skb, dev, ifm, extack, tb, 0);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
@ -3326,6 +3320,7 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
struct ifinfomsg *ifm;
|
||||
char ifname[IFNAMSIZ];
|
||||
struct nlattr **data;
|
||||
bool link_specified;
|
||||
int err;
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
|
@ -3340,18 +3335,17 @@ replay:
|
|||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[IFLA_IFNAME])
|
||||
nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
|
||||
else
|
||||
ifname[0] = '\0';
|
||||
|
||||
ifm = nlmsg_data(nlh);
|
||||
if (ifm->ifi_index > 0)
|
||||
if (ifm->ifi_index > 0) {
|
||||
link_specified = true;
|
||||
dev = __dev_get_by_index(net, ifm->ifi_index);
|
||||
else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
|
||||
dev = rtnl_dev_get(net, NULL, tb[IFLA_ALT_IFNAME], ifname);
|
||||
else
|
||||
} else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME]) {
|
||||
link_specified = true;
|
||||
dev = rtnl_dev_get(net, tb);
|
||||
} else {
|
||||
link_specified = false;
|
||||
dev = NULL;
|
||||
}
|
||||
|
||||
master_dev = NULL;
|
||||
m_ops = NULL;
|
||||
|
@ -3450,15 +3444,20 @@ replay:
|
|||
status |= DO_SETLINK_NOTIFY;
|
||||
}
|
||||
|
||||
return do_setlink(skb, dev, ifm, extack, tb, ifname, status);
|
||||
return do_setlink(skb, dev, ifm, extack, tb, status);
|
||||
}
|
||||
|
||||
if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
|
||||
if (ifm->ifi_index == 0 && tb[IFLA_GROUP])
|
||||
/* No dev found and NLM_F_CREATE not set. Requested dev does not exist,
|
||||
* or it's for a group
|
||||
*/
|
||||
if (link_specified)
|
||||
return -ENODEV;
|
||||
if (tb[IFLA_GROUP])
|
||||
return rtnl_group_changelink(skb, net,
|
||||
nla_get_u32(tb[IFLA_GROUP]),
|
||||
ifm, extack, tb);
|
||||
return -ENODEV;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (tb[IFLA_MAP] || tb[IFLA_PROTINFO])
|
||||
|
@ -3482,7 +3481,9 @@ replay:
|
|||
if (!ops->alloc && !ops->setup)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!ifname[0]) {
|
||||
if (tb[IFLA_IFNAME]) {
|
||||
nla_strscpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ);
|
||||
} else {
|
||||
snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind);
|
||||
name_assign_type = NET_NAME_ENUM;
|
||||
}
|
||||
|
@ -3654,8 +3655,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (ifm->ifi_index > 0)
|
||||
dev = __dev_get_by_index(tgt_net, ifm->ifi_index);
|
||||
else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
|
||||
dev = rtnl_dev_get(tgt_net, tb[IFLA_IFNAME],
|
||||
tb[IFLA_ALT_IFNAME], NULL);
|
||||
dev = rtnl_dev_get(tgt_net, tb);
|
||||
else
|
||||
goto out;
|
||||
|
||||
|
@ -3750,8 +3750,7 @@ static int rtnl_linkprop(int cmd, struct sk_buff *skb, struct nlmsghdr *nlh,
|
|||
if (ifm->ifi_index > 0)
|
||||
dev = __dev_get_by_index(net, ifm->ifi_index);
|
||||
else if (tb[IFLA_IFNAME] || tb[IFLA_ALT_IFNAME])
|
||||
dev = rtnl_dev_get(net, tb[IFLA_IFNAME],
|
||||
tb[IFLA_ALT_IFNAME], NULL);
|
||||
dev = rtnl_dev_get(net, tb);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
|
|
Loading…
Reference in New Issue