| From foo@baz Sat Jan 26 10:22:50 CET 2019 |
| From: Ivan Vecera <ivecera@redhat.com> |
| Date: Wed, 16 Jan 2019 16:53:52 +0100 |
| Subject: net/sched: cls_flower: allocate mask dynamically in fl_change() |
| |
| From: Ivan Vecera <ivecera@redhat.com> |
| |
| [ Upstream commit 2cddd20147826aef283115abb00012d4dafe3cdb ] |
| |
| Recent changes (especially 05cd271fd61a ("cls_flower: Support multiple |
| masks per priority")) in the fl_flow_mask structure grow it and its |
| current size e.g. on x86_64 with defconfig is 760 bytes and more than |
| 1024 bytes with some debug options enabled. Prior the mentioned commit |
| its size was 176 bytes (using defconfig on x86_64). |
| With regard to this fact it's reasonable to allocate this structure |
| dynamically in fl_change() to reduce its stack size. |
| |
| v2: |
| - use kzalloc() instead of kcalloc() |
| |
| Fixes: 05cd271fd61a ("cls_flower: Support multiple masks per priority") |
| Cc: Jiri Pirko <jiri@resnulli.us> |
| Cc: Paul Blakey <paulb@mellanox.com> |
| Acked-by: Jiri Pirko <jiri@mellanox.com> |
| Signed-off-by: Ivan Vecera <ivecera@redhat.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/sched/cls_flower.c | 19 ++++++++++++++----- |
| 1 file changed, 14 insertions(+), 5 deletions(-) |
| |
| --- a/net/sched/cls_flower.c |
| +++ b/net/sched/cls_flower.c |
| @@ -1176,17 +1176,23 @@ static int fl_change(struct net *net, st |
| struct cls_fl_head *head = rtnl_dereference(tp->root); |
| struct cls_fl_filter *fold = *arg; |
| struct cls_fl_filter *fnew; |
| + struct fl_flow_mask *mask; |
| struct nlattr **tb; |
| - struct fl_flow_mask mask = {}; |
| int err; |
| |
| if (!tca[TCA_OPTIONS]) |
| return -EINVAL; |
| |
| - tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL); |
| - if (!tb) |
| + mask = kzalloc(sizeof(struct fl_flow_mask), GFP_KERNEL); |
| + if (!mask) |
| return -ENOBUFS; |
| |
| + tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL); |
| + if (!tb) { |
| + err = -ENOBUFS; |
| + goto errout_mask_alloc; |
| + } |
| + |
| err = nla_parse_nested(tb, TCA_FLOWER_MAX, tca[TCA_OPTIONS], |
| fl_policy, NULL); |
| if (err < 0) |
| @@ -1229,12 +1235,12 @@ static int fl_change(struct net *net, st |
| } |
| } |
| |
| - err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr, |
| + err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr, |
| tp->chain->tmplt_priv, extack); |
| if (err) |
| goto errout_idr; |
| |
| - err = fl_check_assign_mask(head, fnew, fold, &mask); |
| + err = fl_check_assign_mask(head, fnew, fold, mask); |
| if (err) |
| goto errout_idr; |
| |
| @@ -1278,6 +1284,7 @@ static int fl_change(struct net *net, st |
| } |
| |
| kfree(tb); |
| + kfree(mask); |
| return 0; |
| |
| errout_mask: |
| @@ -1291,6 +1298,8 @@ errout: |
| kfree(fnew); |
| errout_tb: |
| kfree(tb); |
| +errout_mask_alloc: |
| + kfree(mask); |
| return err; |
| } |
| |