Message ID | 20240710151653.3786604-1-edumazet@google.com (mailing list archive) |
---|---|
State | Accepted |
Commit | cef4902b0fadfc4181176ef5713f0b7cf2a40d8f |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | [v2,net-next] net: reduce rtnetlink_rcv_msg() stack usage | expand |
On Wed, Jul 10, 2024 at 03:16:53PM +0000, Eric Dumazet wrote: > IFLA_MAX is increasing slowly but surely. > > Some compilers use more than 512 bytes of stack in rtnetlink_rcv_msg() > because it calls rtnl_calcit() for RTM_GETLINK message. > > Use noinline_for_stack attribute to not inline rtnl_calcit(), > and directly use nla_for_each_attr_type() (Jakub suggestion) > because we only care about IFLA_EXT_MASK at this stage. > > Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Simon Horman <horms@kernel.org> > --- > net/core/rtnetlink.c | 18 ++++++++++++------ > 1 file changed, 12 insertions(+), 6 deletions(-) > > diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c > index eabfc8290f5e29f2ef3e5c1481715ae9056ea689..87e67194f24046a8420bbb51c19fb0a686b9b06b 100644 > --- a/net/core/rtnetlink.c > +++ b/net/core/rtnetlink.c > @@ -3969,22 +3969,28 @@ static int rtnl_dellinkprop(struct sk_buff *skb, struct nlmsghdr *nlh, > return rtnl_linkprop(RTM_DELLINKPROP, skb, nlh, extack); > } > > -static u32 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh) > +static noinline_for_stack u32 rtnl_calcit(struct sk_buff *skb, > + struct nlmsghdr *nlh) > { > struct net *net = sock_net(skb->sk); > size_t min_ifinfo_dump_size = 0; > - struct nlattr *tb[IFLA_MAX+1]; > u32 ext_filter_mask = 0; > struct net_device *dev; > - int hdrlen; > + struct nlattr *nla; > + int hdrlen, rem; > > /* Same kernel<->userspace interface hack as in rtnl_dump_ifinfo. */ > hdrlen = nlmsg_len(nlh) < sizeof(struct ifinfomsg) ? > sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg); > > - if (nlmsg_parse_deprecated(nlh, hdrlen, tb, IFLA_MAX, ifla_policy, NULL) >= 0) { > - if (tb[IFLA_EXT_MASK]) > - ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); > + if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) > + return NLMSG_GOODSIZE; > + > + nla_for_each_attr_type(nla, IFLA_EXT_MASK, > + nlmsg_attrdata(nlh, hdrlen), > + nlmsg_attrlen(nlh, hdrlen), rem) { > + if (nla_len(nla) == sizeof(u32)) > + ext_filter_mask = nla_get_u32(nla); I guess that in practice we can break here. But perhaps there is some case where there is more than one IFLA_EXT_MASK attribute and it changes behaviour. > } > > if (!ext_filter_mask) > -- > 2.45.2.993.g49e7a77208-goog > >
Hello: This patch was applied to netdev/net-next.git (main) by Jakub Kicinski <kuba@kernel.org>: On Wed, 10 Jul 2024 15:16:53 +0000 you wrote: > IFLA_MAX is increasing slowly but surely. > > Some compilers use more than 512 bytes of stack in rtnetlink_rcv_msg() > because it calls rtnl_calcit() for RTM_GETLINK message. > > Use noinline_for_stack attribute to not inline rtnl_calcit(), > and directly use nla_for_each_attr_type() (Jakub suggestion) > because we only care about IFLA_EXT_MASK at this stage. > > [...] Here is the summary with links: - [v2,net-next] net: reduce rtnetlink_rcv_msg() stack usage https://git.kernel.org/netdev/net-next/c/cef4902b0fad You are awesome, thank you!
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index eabfc8290f5e29f2ef3e5c1481715ae9056ea689..87e67194f24046a8420bbb51c19fb0a686b9b06b 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3969,22 +3969,28 @@ static int rtnl_dellinkprop(struct sk_buff *skb, struct nlmsghdr *nlh, return rtnl_linkprop(RTM_DELLINKPROP, skb, nlh, extack); } -static u32 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh) +static noinline_for_stack u32 rtnl_calcit(struct sk_buff *skb, + struct nlmsghdr *nlh) { struct net *net = sock_net(skb->sk); size_t min_ifinfo_dump_size = 0; - struct nlattr *tb[IFLA_MAX+1]; u32 ext_filter_mask = 0; struct net_device *dev; - int hdrlen; + struct nlattr *nla; + int hdrlen, rem; /* Same kernel<->userspace interface hack as in rtnl_dump_ifinfo. */ hdrlen = nlmsg_len(nlh) < sizeof(struct ifinfomsg) ? sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg); - if (nlmsg_parse_deprecated(nlh, hdrlen, tb, IFLA_MAX, ifla_policy, NULL) >= 0) { - if (tb[IFLA_EXT_MASK]) - ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); + if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) + return NLMSG_GOODSIZE; + + nla_for_each_attr_type(nla, IFLA_EXT_MASK, + nlmsg_attrdata(nlh, hdrlen), + nlmsg_attrlen(nlh, hdrlen), rem) { + if (nla_len(nla) == sizeof(u32)) + ext_filter_mask = nla_get_u32(nla); } if (!ext_filter_mask)
IFLA_MAX is increasing slowly but surely. Some compilers use more than 512 bytes of stack in rtnetlink_rcv_msg() because it calls rtnl_calcit() for RTM_GETLINK message. Use noinline_for_stack attribute to not inline rtnl_calcit(), and directly use nla_for_each_attr_type() (Jakub suggestion) because we only care about IFLA_EXT_MASK at this stage. Signed-off-by: Eric Dumazet <edumazet@google.com> --- net/core/rtnetlink.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)