summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavide Caratti <dcaratti@redhat.com>2018-11-28 12:43:42 -0500
committerDavid S. Miller <davem@davemloft.net>2018-11-30 20:14:06 -0500
commitfd6d433865a2ad1f7e018ef80408cb3dc3be1ab3 (patch)
tree69b461021adc9a6fedfeec8faaed3c8e7badb805 /net
parentb5f0cf08340090d1503dbdbfd797e32264974100 (diff)
net/sched: act_police: fix memory leak in case of invalid control action
when users set an invalid control action, kmemleak complains as follows: # echo clear >/sys/kernel/debug/kmemleak # ./tdc.py -e b48b Test b48b: Add police action with exceed goto chain control action All test results: 1..1 ok 1 - b48b # Add police action with exceed goto chain control action about to flush the tap output if tests need to be skipped done flushing skipped test tap output # echo scan >/sys/kernel/debug/kmemleak # cat /sys/kernel/debug/kmemleak unreferenced object 0xffffa0fafbc3dde0 (size 96): comm "tc", pid 2358, jiffies 4294922738 (age 17.022s) hex dump (first 32 bytes): 2a 00 00 20 00 00 00 00 00 00 7d 00 00 00 00 00 *.. ......}..... f8 07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace: [<00000000648803d2>] tcf_action_init_1+0x384/0x4c0 [<00000000cb69382e>] tcf_action_init+0x12b/0x1a0 [<00000000847ef0d4>] tcf_action_add+0x73/0x170 [<0000000093656e14>] tc_ctl_action+0x122/0x160 [<0000000023c98e32>] rtnetlink_rcv_msg+0x263/0x2d0 [<000000003493ae9c>] netlink_rcv_skb+0x4d/0x130 [<00000000de63f8ba>] netlink_unicast+0x209/0x2d0 [<00000000c3da0ebe>] netlink_sendmsg+0x2c1/0x3c0 [<000000007a9e0753>] sock_sendmsg+0x33/0x40 [<00000000457c6d2e>] ___sys_sendmsg+0x2a0/0x2f0 [<00000000c5c6a086>] __sys_sendmsg+0x5e/0xa0 [<00000000446eafce>] do_syscall_64+0x5b/0x180 [<000000004aa871f2>] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [<00000000450c38ef>] 0xffffffffffffffff change tcf_police_init() to avoid leaking 'new' in case TCA_POLICE_RESULT contains TC_ACT_GOTO_CHAIN extended action. Fixes: c08f5ed5d625 ("net/sched: act_police: disallow 'goto chain' on fallback control action") Reported-by: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Davide Caratti <dcaratti@redhat.com> Acked-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/sched/act_police.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 37c9b8f0e10f..ec8ec55e0fe8 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -85,7 +85,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
85 int ovr, int bind, bool rtnl_held, 85 int ovr, int bind, bool rtnl_held,
86 struct netlink_ext_ack *extack) 86 struct netlink_ext_ack *extack)
87{ 87{
88 int ret = 0, err; 88 int ret = 0, tcfp_result = TC_ACT_OK, err, size;
89 struct nlattr *tb[TCA_POLICE_MAX + 1]; 89 struct nlattr *tb[TCA_POLICE_MAX + 1];
90 struct tc_police *parm; 90 struct tc_police *parm;
91 struct tcf_police *police; 91 struct tcf_police *police;
@@ -93,7 +93,6 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
93 struct tc_action_net *tn = net_generic(net, police_net_id); 93 struct tc_action_net *tn = net_generic(net, police_net_id);
94 struct tcf_police_params *new; 94 struct tcf_police_params *new;
95 bool exists = false; 95 bool exists = false;
96 int size;
97 96
98 if (nla == NULL) 97 if (nla == NULL)
99 return -EINVAL; 98 return -EINVAL;
@@ -160,6 +159,16 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
160 goto failure; 159 goto failure;
161 } 160 }
162 161
162 if (tb[TCA_POLICE_RESULT]) {
163 tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
164 if (TC_ACT_EXT_CMP(tcfp_result, TC_ACT_GOTO_CHAIN)) {
165 NL_SET_ERR_MSG(extack,
166 "goto chain not allowed on fallback");
167 err = -EINVAL;
168 goto failure;
169 }
170 }
171
163 new = kzalloc(sizeof(*new), GFP_KERNEL); 172 new = kzalloc(sizeof(*new), GFP_KERNEL);
164 if (unlikely(!new)) { 173 if (unlikely(!new)) {
165 err = -ENOMEM; 174 err = -ENOMEM;
@@ -167,6 +176,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
167 } 176 }
168 177
169 /* No failure allowed after this point */ 178 /* No failure allowed after this point */
179 new->tcfp_result = tcfp_result;
170 new->tcfp_mtu = parm->mtu; 180 new->tcfp_mtu = parm->mtu;
171 if (!new->tcfp_mtu) { 181 if (!new->tcfp_mtu) {
172 new->tcfp_mtu = ~0; 182 new->tcfp_mtu = ~0;
@@ -196,16 +206,6 @@ static int tcf_police_init(struct net *net, struct nlattr *nla,
196 if (tb[TCA_POLICE_AVRATE]) 206 if (tb[TCA_POLICE_AVRATE])
197 new->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]); 207 new->tcfp_ewma_rate = nla_get_u32(tb[TCA_POLICE_AVRATE]);
198 208
199 if (tb[TCA_POLICE_RESULT]) {
200 new->tcfp_result = nla_get_u32(tb[TCA_POLICE_RESULT]);
201 if (TC_ACT_EXT_CMP(new->tcfp_result, TC_ACT_GOTO_CHAIN)) {
202 NL_SET_ERR_MSG(extack,
203 "goto chain not allowed on fallback");
204 err = -EINVAL;
205 goto failure;
206 }
207 }
208
209 spin_lock_bh(&police->tcf_lock); 209 spin_lock_bh(&police->tcf_lock);
210 spin_lock_bh(&police->tcfp_lock); 210 spin_lock_bh(&police->tcfp_lock);
211 police->tcfp_t_c = ktime_get_ns(); 211 police->tcfp_t_c = ktime_get_ns();