Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: sched: cls_matchall: Undo tcf_bind_filter in case of failure after mall_set_parms

In case an error occurred after mall_set_parms executed successfully, we
must undo the tcf_bind_filter call it issues.

Fix that by calling tcf_unbind_filter in err_replace_hw_filter label.

Fixes: ec2507d2a306 ("net/sched: cls_matchall: Fix error path")
Signed-off-by: Victor Nogueira <victor@mojatatu.com>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Reviewed-by: Pedro Tammela <pctammela@mojatatu.com>
Reviewed-by: Simon Horman <simon.horman@corigine.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Victor Nogueira and committed by
David S. Miller
b3d0e048 0dd1805f

+12 -23
+12 -23
net/sched/cls_matchall.c
··· 159 159 [TCA_MATCHALL_FLAGS] = { .type = NLA_U32 }, 160 160 }; 161 161 162 - static int mall_set_parms(struct net *net, struct tcf_proto *tp, 163 - struct cls_mall_head *head, 164 - unsigned long base, struct nlattr **tb, 165 - struct nlattr *est, u32 flags, u32 fl_flags, 166 - struct netlink_ext_ack *extack) 167 - { 168 - int err; 169 - 170 - err = tcf_exts_validate_ex(net, tp, tb, est, &head->exts, flags, 171 - fl_flags, extack); 172 - if (err < 0) 173 - return err; 174 - 175 - if (tb[TCA_MATCHALL_CLASSID]) { 176 - head->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]); 177 - tcf_bind_filter(tp, &head->res, base); 178 - } 179 - return 0; 180 - } 181 - 182 162 static int mall_change(struct net *net, struct sk_buff *in_skb, 183 163 struct tcf_proto *tp, unsigned long base, 184 164 u32 handle, struct nlattr **tca, ··· 167 187 { 168 188 struct cls_mall_head *head = rtnl_dereference(tp->root); 169 189 struct nlattr *tb[TCA_MATCHALL_MAX + 1]; 190 + bool bound_to_filter = false; 170 191 struct cls_mall_head *new; 171 192 u32 userflags = 0; 172 193 int err; ··· 207 226 goto err_alloc_percpu; 208 227 } 209 228 210 - err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE], 211 - flags, new->flags, extack); 212 - if (err) 229 + err = tcf_exts_validate_ex(net, tp, tb, tca[TCA_RATE], 230 + &new->exts, flags, new->flags, extack); 231 + if (err < 0) 213 232 goto err_set_parms; 233 + 234 + if (tb[TCA_MATCHALL_CLASSID]) { 235 + new->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]); 236 + tcf_bind_filter(tp, &new->res, base); 237 + bound_to_filter = true; 238 + } 214 239 215 240 if (!tc_skip_hw(new->flags)) { 216 241 err = mall_replace_hw_filter(tp, new, (unsigned long)new, ··· 233 246 return 0; 234 247 235 248 err_replace_hw_filter: 249 + if (bound_to_filter) 250 + tcf_unbind_filter(tp, &new->res); 236 251 err_set_parms: 237 252 free_percpu(new->pf); 238 253 err_alloc_percpu: