Commit b57e1fff authored by David S. Miller's avatar David S. Miller

Merge branch 'vlan-rtnetlink-newlink-fixes'

Eric Dumazet says:

====================
vlan: rtnetlink newlink fixes

First patch fixes a potential memory leak found by syzbot

Second patch makes vlan_changelink() aware of errors
and report them to user.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 96b11e93 eb8ef2a3
...@@ -126,6 +126,7 @@ int vlan_check_real_dev(struct net_device *real_dev, ...@@ -126,6 +126,7 @@ int vlan_check_real_dev(struct net_device *real_dev,
void vlan_setup(struct net_device *dev); void vlan_setup(struct net_device *dev);
int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack); int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack);
void unregister_vlan_dev(struct net_device *dev, struct list_head *head); void unregister_vlan_dev(struct net_device *dev, struct list_head *head);
void vlan_dev_uninit(struct net_device *dev);
bool vlan_dev_inherit_address(struct net_device *dev, bool vlan_dev_inherit_address(struct net_device *dev,
struct net_device *real_dev); struct net_device *real_dev);
......
...@@ -586,7 +586,8 @@ static int vlan_dev_init(struct net_device *dev) ...@@ -586,7 +586,8 @@ static int vlan_dev_init(struct net_device *dev)
return 0; return 0;
} }
static void vlan_dev_uninit(struct net_device *dev) /* Note: this function might be called multiple times for the same device. */
void vlan_dev_uninit(struct net_device *dev)
{ {
struct vlan_priority_tci_mapping *pm; struct vlan_priority_tci_mapping *pm;
struct vlan_dev_priv *vlan = vlan_dev_priv(dev); struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
......
...@@ -108,11 +108,13 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -108,11 +108,13 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
struct ifla_vlan_flags *flags; struct ifla_vlan_flags *flags;
struct ifla_vlan_qos_mapping *m; struct ifla_vlan_qos_mapping *m;
struct nlattr *attr; struct nlattr *attr;
int rem; int rem, err;
if (data[IFLA_VLAN_FLAGS]) { if (data[IFLA_VLAN_FLAGS]) {
flags = nla_data(data[IFLA_VLAN_FLAGS]); flags = nla_data(data[IFLA_VLAN_FLAGS]);
vlan_dev_change_flags(dev, flags->flags, flags->mask); err = vlan_dev_change_flags(dev, flags->flags, flags->mask);
if (err)
return err;
} }
if (data[IFLA_VLAN_INGRESS_QOS]) { if (data[IFLA_VLAN_INGRESS_QOS]) {
nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) { nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
...@@ -123,7 +125,9 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[], ...@@ -123,7 +125,9 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
if (data[IFLA_VLAN_EGRESS_QOS]) { if (data[IFLA_VLAN_EGRESS_QOS]) {
nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) { nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
m = nla_data(attr); m = nla_data(attr);
vlan_dev_set_egress_priority(dev, m->from, m->to); err = vlan_dev_set_egress_priority(dev, m->from, m->to);
if (err)
return err;
} }
} }
return 0; return 0;
...@@ -179,10 +183,11 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev, ...@@ -179,10 +183,11 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev,
return -EINVAL; return -EINVAL;
err = vlan_changelink(dev, tb, data, extack); err = vlan_changelink(dev, tb, data, extack);
if (err < 0) if (!err)
err = register_vlan_dev(dev, extack);
if (err)
vlan_dev_uninit(dev);
return err; return err;
return register_vlan_dev(dev, extack);
} }
static inline size_t vlan_qos_map_size(unsigned int n) static inline size_t vlan_qos_map_size(unsigned int n)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment