fix idr leak in actions
Subsystems (5)
v2 cover fix idr leak in actions
This series fixes situations where a temporary failure to install a TC action results in the permanent impossibility to reuse the configured value of 'index'.
Thanks to Cong Wang for the initial review.
v2: fix build error in act_ipt.c, reported by kbuild test robot
Davide Caratti (7):
net/sched: fix idr leak on the error path of tcf_bpf_init() net/sched: fix idr leak in the error path of tcf_simp_init() net/sched: fix idr leak in the error path of tcf_act_police_init() net/sched: fix idr leak in the error path of tcp_pedit_init() net/sched: fix idr leak in the error path of __tcf_ipt_init() net/sched: fix idr leak in the error path of tcf_vlan_init() net/sched: fix idr leak in the error path of tcf_skbmod_init()
net/sched/act_bpf.c | 2 +- net/sched/act_ipt.c | 9 ++++++--- net/sched/act_pedit.c | 2 +- net/sched/act_police.c | 2 +- net/sched/act_simple.c | 2 +- net/sched/act_skbmod.c | 2 +- net/sched/act_vlan.c | 2 +- 7 files changed, 12 insertions(+), 9 deletions(-)
Signature · 1 line
2.14.3
PATCH v2 1/7 net/sched: fix idr leak on the error path of tcf_bpf_init()
when the following command sequence is entered
# tc action add action bpf bytecode '4,40 0 0 12,31 0 1 2048,6 0 0 262144,6 0 0 0' index 100 RTNETLINK answers: Invalid argument We have an error talking to the kernel # tc action add action bpf bytecode '4,40 0 0 12,21 0 1 2048,6 0 0 262144,6 0 0 0' index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel
act_bpf correctly refuses to install the first TC rule, because 31 is not a valid instruction. However, it refuses to install the second TC rule, even if the BPF code is correct. Furthermore, it's no more possible to install any other rule having the same value of 'index' until act_bpf module is unloaded/inserted again. After the idr has been reserved, call tcf_idr_release() instead of tcf_idr_cleanup(), to fix this issue.
--- net/sched/act_bpf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_bpf.c +1 -1
@@ -352,7 +352,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla,return res; out:if (res ==ACT_P_CREATED ) -tcf_idr_cleanup (*act, est); +tcf_idr_release (*act, bind);return ret; }
Signature · 1 line
2.14.3
PATCH v2 2/7 net/sched: fix idr leak in the error path of tcf_simp_init()
In reply to Davide Carattiif the kernel fails to duplicate 'sdata', creation of a new action fails with -ENOMEM. However, subsequent attempts to install the same action using the same value of 'index' systematically fail with -ENOSPC, and that value of 'index' will no more be usable by act_simple, until rmmod / insmod of act_simple.ko is done:
# tc actions add action simple sdata hello index 100 # tc actions list action simple
action order 0: Simple <hello>
index 100 ref 1 bind 0
# tc actions flush action simple # tc actions add action simple sdata hello index 100 RTNETLINK answers: Cannot allocate memory We have an error talking to the kernel # tc actions flush action simple # tc actions add action simple sdata hello index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel # tc actions add action simple sdata hello index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel ...
Fix this in the error path of tcf_simp_init(), calling tcf_idr_release() in place of tcf_idr_cleanup().
--- net/sched/act_simple.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_simple.c +1 -1
@@ -121,7 +121,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, d =to_defact (*a); ret =alloc_defdata (d, defdata);if (ret <0 ) { -tcf_idr_cleanup (*a, est); +tcf_idr_release (*a, bind);return ret; } d->tcf_action = parm->action;
Signature · 1 line
2.14.3
PATCH v2 3/7 net/sched: fix idr leak in the error path of tcf_act_police_init()
In reply to Davide Carattitcf_act_police_init() can fail after the idr has been successfully reserved (e.g., qdisc_get_rtab() may return NULL). When this happens, subsequent attempts to configure a police rule using the same idr value systematiclly fail with -ENOSPC:
# tc action add action police rate 1000 burst 1000 drop index 100 RTNETLINK answers: Cannot allocate memory We have an error talking to the kernel # tc action add action police rate 1000 burst 1000 drop index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel # tc action add action police rate 1000 burst 1000 drop index 100 RTNETLINK answers: No space left on device ...
Fix this in the error path of tcf_act_police_init(), calling tcf_idr_release() in place of tcf_idr_cleanup().
--- net/sched/act_police.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_police.c +1 -1
@@ -194,7 +194,7 @@ static int tcf_act_police_init(struct net *net, struct nlattr *nla,qdisc_put_rtab (P_tab);qdisc_put_rtab (R_tab);if (ret ==ACT_P_CREATED ) -tcf_idr_cleanup (*a, est); +tcf_idr_release (*a, bind);return err; }
Signature · 1 line
2.14.3
PATCH v2 4/7 net/sched: fix idr leak in the error path of tcp_pedit_init()
In reply to Davide Carattitcf_pedit_init() can fail to allocate 'keys' after the idr has been successfully reserved. When this happens, subsequent attempts to configure a pedit rule using the same idr value systematically fail with -ENOSPC:
# tc action add action pedit munge ip ttl set 63 index 100 RTNETLINK answers: Cannot allocate memory We have an error talking to the kernel # tc action add action pedit munge ip ttl set 63 index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel # tc action add action pedit munge ip ttl set 63 index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel ...
Fix this in the error path of tcf_act_pedit_init(), calling tcf_idr_release() in place of tcf_idr_cleanup().
--- net/sched/act_pedit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_pedit.c +1 -1
@@ -176,7 +176,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, p =to_pedit (*a); keys =kmalloc (ksize,GFP_KERNEL );if (keys ==NULL ) { -tcf_idr_cleanup (*a, est); +tcf_idr_release (*a, bind);kfree (keys_ex);return -ENOMEM ; }
Signature · 1 line
2.14.3
PATCH v2 5/7 net/sched: fix idr leak in the error path of __tcf_ipt_init()
In reply to Davide Caratti__tcf_ipt_init() can fail after the idr has been successfully reserved. When this happens, subsequent attempts to configure xt/ipt rules using the same idr value systematically fail with -ENOSPC:
# tc action add action xt -j LOG --log-prefix test1 index 100
tablename: mangle hook: NF_IP_POST_ROUTING
target: LOG level warning prefix "test1" index 100
RTNETLINK answers: Cannot allocate memory
We have an error talking to the kernel
Command "(null)" is unknown, try "tc actions help".
# tc action add action xt -j LOG --log-prefix test1 index 100
tablename: mangle hook: NF_IP_POST_ROUTING
target: LOG level warning prefix "test1" index 100
RTNETLINK answers: No space left on device
We have an error talking to the kernel
Command "(null)" is unknown, try "tc actions help".
# tc action add action xt -j LOG --log-prefix test1 index 100
tablename: mangle hook: NF_IP_POST_ROUTING
target: LOG level warning prefix "test1" index 100
RTNETLINK answers: No space left on device
We have an error talking to the kernel
...Fix this in the error path of __tcf_ipt_init(), calling tcf_idr_release() in place of tcf_idr_cleanup(). Since tcf_ipt_release() can now be called when tcfi_t is NULL, we also need to protect calls to ipt_destroy_target() to avoid NULL pointer dereference.
--- net/sched/act_ipt.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
net/sched/act_ipt.c +6 -3
@@ -80,9 +80,12 @@ static void ipt_destroy_target(struct xt_entry_target *t)static void tcf_ipt_release (struct tc_action *a) {struct tcf_ipt *ipt =to_ipt (a); -ipt_destroy_target (ipt->tcfi_t); + +if (ipt->tcfi_t) { +ipt_destroy_target (ipt->tcfi_t); +kfree (ipt->tcfi_t); + }kfree (ipt->tcfi_tname); -kfree (ipt->tcfi_t); }static const struct nla_policy ipt_policy[TCA_IPT_MAX +1 ] = {
@@ -187,7 +190,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,kfree (tname); err1:if (ret ==ACT_P_CREATED ) -tcf_idr_cleanup (*a, est); +tcf_idr_release (*a, bind);return err; }
Signature · 1 line
2.14.3
PATCH v2 6/7 net/sched: fix idr leak in the error path of tcf_vlan_init()
In reply to Davide Carattitcf_vlan_init() can fail after the idr has been successfully reserved. When this happens, every subsequent attempt to configure vlan rules using the same idr value will systematically fail with -ENOSPC, unless the first attempt was done using the 'replace' keyword.
# tc action add action vlan pop index 100 RTNETLINK answers: Cannot allocate memory We have an error talking to the kernel # tc action add action vlan pop index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel # tc action add action vlan pop index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel ...
Fix this in tcf_vlan_init(), ensuring that tcf_idr_release() is called on the error path when the idr has been reserved, but not yet inserted. Also, don't test 'ovr' in the error path, to avoid a 'replace' failure implicitly become a 'delete' that leaks refcount in act_vlan module:
# rmmod act_vlan; modprobe act_vlan # tc action add action vlan push id 5 index 100 # tc action replace action vlan push id 7 index 100 RTNETLINK answers: Cannot allocate memory We have an error talking to the kernel # tc action list action vlan # # rmmod act_vlan rmmod: ERROR: Module act_vlan is in use
--- net/sched/act_vlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_vlan.c +1 -1
@@ -195,7 +195,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla,ASSERT_RTNL (); p =kzalloc (sizeof (*p),GFP_KERNEL );if (!p) { -if (ovr) +if (ret ==ACT_P_CREATED )tcf_idr_release (*a, bind);return -ENOMEM ; }
Signature · 1 line
2.14.3
PATCH v2 7/7 net/sched: fix idr leak in the error path of tcf_skbmod_init()
In reply to Davide Carattitcf_skbmod_init() can fail after the idr has been successfully reserved. When this happens, every subsequent attempt to configure skbmod rules using the same idr value will systematically fail with -ENOSPC, unless the first attempt was done using the 'replace' keyword:
# tc action add action skbmod swap mac index 100 RTNETLINK answers: Cannot allocate memory We have an error talking to the kernel # tc action add action skbmod swap mac index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel # tc action add action skbmod swap mac index 100 RTNETLINK answers: No space left on device We have an error talking to the kernel ...
Fix this in tcf_skbmod_init(), ensuring that tcf_idr_release() is called on the error path when the idr has been reserved, but not yet inserted. Also, don't test 'ovr' in the error path, to avoid a 'replace' failure implicitly become a 'delete' that leaks refcount in act_skbmod module:
# rmmod act_skbmod; modprobe act_skbmod # tc action add action skbmod swap mac index 100 # tc action add action skbmod swap mac continue index 100 RTNETLINK answers: File exists We have an error talking to the kernel # tc action replace action skbmod swap mac continue index 100 RTNETLINK answers: Cannot allocate memory We have an error talking to the kernel # tc action list action skbmod # # rmmod act_skbmod rmmod: ERROR: Module act_skbmod is in use
--- net/sched/act_skbmod.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_skbmod.c +1 -1
@@ -152,7 +152,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,ASSERT_RTNL (); p =kzalloc (sizeof (struct tcf_skbmod_params ),GFP_KERNEL );if (unlikely (!p)) { -if (ovr) +if (ret ==ACT_P_CREATED )tcf_idr_release (*a, bind);return -ENOMEM ; }
Signature · 1 line
2.14.3
Quoted 7 lines · Davide Caratti
This series fixes situations where a temporary failure to install a TC action results in the permanent impossibility to reuse the configured value of 'index'.
Thanks to Cong Wang for the initial review.
v2: fix build error in
act_ipt.c, reported by kbuild test robot
Looks good. Just a nit: seems tcf_idr_cleanup() can be removed after your patchset. If so, please send a followup patch after these patches merged into net-next.
David Miller
maintainerFrom: Davide Caratti <[email protected]>
Date: Mon, 19 Mar 2018 15:31:21 +0100
Quoted 7 lines
This series fixes situations where a temporary failure to install a TC action results in the permanent impossibility to reuse the configured value of 'index'.
Thanks to Cong Wang for the initial review.
v2: fix build error in
act_ipt.c, reported by kbuild test robot
Series applied, thanks Davide.