From db0ce3400e98b1d66aaf3b273082726e7413554e Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 27 Nov 2018 22:32:31 -0800 Subject: [PATCH 2435/2944] rtnetlink: avoid frame size warning in rtnl_newlink() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix #31615004 commit a293974590cfdc2d59c559a54d62a5ecb648104b upstream. Standard kernel compilation produces the following warning: net/core/rtnetlink.c: In function ‘rtnl_newlink’: net/core/rtnetlink.c:3232:1: warning: the frame size of 1288 bytes is larger than 1024 bytes [-Wframe-larger-than=] } ^ This should not really be an issue, as rtnl_newlink() stack is generally quite shallow. Fix the warning by allocating attributes with kmalloc() in a wrapper and passing it down to rtnl_newlink(), avoiding complexities on error paths. Alternatively we could kmalloc() some structure within rtnl_newlink(), slave attributes look like a good candidate. In practice it adds to already rather high complexity and length of the function. Conflict resove: - The conflict is introduced by commit 420d03182273 ("rtnetlink: remove a level of indentation in rtnl_newlink()"), which move some of the stack variables out of the if (1) {} to the function's top level. - Since 420d03182273 has a depedency on commit ccf8dbcd062a ("rtnetlink: Remove VLA usage"), we didn't backport it. Signed-off-by: Jakub Kicinski Reviewed-by: David Ahern Signed-off-by: David S. Miller Signed-off-by: Dust Li Reviewed-by: Xuan Zhuo Acked-by: Tony Lu --- net/core/rtnetlink.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index dbb3c0c..3fbaff6 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2922,8 +2922,8 @@ 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 net *net = sock_net(skb->sk); const struct rtnl_link_ops *ops; @@ -2992,7 +2992,6 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, } 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; @@ -3180,6 +3179,21 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, } } +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, struct netlink_ext_ack *extack) { -- 1.8.3.1