Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd354208 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'rtnetlink-avoid-a-warning-in-rtnl_newlink'



Jakub Kicinski says:

====================
rtnetlink: avoid a warning in rtnl_newlink()

I've been hoping for some time that someone more competent would fix
the stack frame size warning in rtnl_newlink(), but looks like I'll
have to take a stab at it myself :)  That's the only warning I see
in most of my builds.

First patch refactors away a somewhat surprising if (1) code block.
Reindentation will most likely cause cherry-pick problems but OTOH
rtnl_newlink() doesn't seem to be changed often, so perhaps we can
risk it in the name of cleaner code?

Second patch fixes the warning in simplest possible way.  I was
pondering if there is any more clever solution, but I can't see it..
rtnl_newlink() is quite long with a lot of possible execution paths
so doing memory allocations half way through leads to very ugly
results.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 74315c39 a2939745
Loading
Loading
Loading
Loading
+170 −161
Original line number Diff line number Diff line
@@ -2971,20 +2971,24 @@ static int rtnl_group_changelink(const struct sk_buff *skb,
	return 0;
}

static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
			struct netlink_ext_ack *extack)
static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
			  struct nlattr **attr, struct netlink_ext_ack *extack)
{
	struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1];
	unsigned char name_assign_type = NET_NAME_USER;
	struct nlattr *linkinfo[IFLA_INFO_MAX + 1];
	const struct rtnl_link_ops *m_ops = NULL;
	struct net_device *master_dev = NULL;
	struct net *net = sock_net(skb->sk);
	const struct rtnl_link_ops *ops;
	const struct rtnl_link_ops *m_ops = NULL;
	struct nlattr *tb[IFLA_MAX + 1];
	struct net *dest_net, *link_net;
	struct nlattr **slave_data;
	char kind[MODULE_NAME_LEN];
	struct net_device *dev;
	struct net_device *master_dev = NULL;
	struct ifinfomsg *ifm;
	char kind[MODULE_NAME_LEN];
	char ifname[IFNAMSIZ];
	struct nlattr *tb[IFLA_MAX+1];
	struct nlattr *linkinfo[IFLA_INFO_MAX+1];
	unsigned char name_assign_type = NET_NAME_USER;
	struct nlattr **data;
	int err;

#ifdef CONFIG_MODULES
@@ -3040,13 +3044,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
		ops = NULL;
	}

	if (1) {
		struct nlattr *attr[RTNL_MAX_TYPE + 1];
		struct nlattr *slave_attr[RTNL_SLAVE_MAX_TYPE + 1];
		struct nlattr **data = NULL;
		struct nlattr **slave_data = NULL;
		struct net *dest_net, *link_net = NULL;

	data = NULL;
	if (ops) {
		if (ops->maxtype > RTNL_MAX_TYPE)
			return -EINVAL;
@@ -3066,17 +3064,16 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
		}
	}

	slave_data = NULL;
	if (m_ops) {
		if (m_ops->slave_maxtype > RTNL_SLAVE_MAX_TYPE)
			return -EINVAL;

		if (m_ops->slave_maxtype &&
		    linkinfo[IFLA_INFO_SLAVE_DATA]) {
				err = nla_parse_nested(slave_attr,
						       m_ops->slave_maxtype,
			err = nla_parse_nested(slave_attr, m_ops->slave_maxtype,
					       linkinfo[IFLA_INFO_SLAVE_DATA],
						       m_ops->slave_policy,
						       extack);
					       m_ops->slave_policy, extack);
			if (err < 0)
				return err;
			slave_data = slave_attr;
@@ -3106,16 +3103,14 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
			if (!m_ops || !m_ops->slave_changelink)
				return -EOPNOTSUPP;

				err = m_ops->slave_changelink(master_dev, dev,
							      tb, slave_data,
							      extack);
			err = m_ops->slave_changelink(master_dev, dev, tb,
						      slave_data, extack);
			if (err < 0)
				return err;
			status |= DO_SETLINK_NOTIFY;
		}

			return do_setlink(skb, dev, ifm, extack, tb, ifname,
					  status);
		return do_setlink(skb, dev, ifm, extack, tb, ifname, status);
	}

	if (!(nlh->nlmsg_flags & NLM_F_CREATE)) {
@@ -3168,6 +3163,8 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
		err = -EPERM;
		if (!netlink_ns_capable(skb, link_net->user_ns, CAP_NET_ADMIN))
			goto out;
	} else {
		link_net = NULL;
	}

	dev = rtnl_create_link(link_net ? : dest_net, ifname,
@@ -3180,8 +3177,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
	dev->ifindex = ifm->ifi_index;

	if (ops->newlink) {
			err = ops->newlink(link_net ? : net, dev, tb, data,
					   extack);
		err = ops->newlink(link_net ? : net, dev, tb, data, extack);
		/* Drivers should call free_netdev() in ->destructor
		 * and unregister it on failure after registration
		 * so that device could be finally freed in rtnl_unlock.
@@ -3208,8 +3204,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
			goto out_unregister;
	}
	if (tb[IFLA_MASTER]) {
			err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]),
					    extack);
		err = do_set_master(dev, nla_get_u32(tb[IFLA_MASTER]), extack);
		if (err)
			goto out_unregister;
	}
@@ -3229,6 +3224,20 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
	}
	goto out;
}

static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
			struct netlink_ext_ack *extack)
{
	struct nlattr **attr;
	int ret;

	attr = kmalloc_array(RTNL_MAX_TYPE + 1, sizeof(*attr), GFP_KERNEL);
	if (!attr)
		return -ENOMEM;

	ret = __rtnl_newlink(skb, nlh, attr, extack);
	kfree(attr);
	return ret;
}

static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr *nlh,