diff options
author | Davide Caratti <dcaratti@redhat.com> | 2018-11-28 12:43:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-11-30 20:14:06 -0500 |
commit | fd6d433865a2ad1f7e018ef80408cb3dc3be1ab3 (patch) | |
tree | 69b461021adc9a6fedfeec8faaed3c8e7badb805 /net | |
parent | b5f0cf08340090d1503dbdbfd797e32264974100 (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.c | 24 |
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(); |