Skip to contentSkip to conversation

fix idr leak in actions

PATCH In review Davide Caratti 3 participants 10 messages Mar 19, 2018 – Mar 21, 2018

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

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
#1 lore raw

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.

Fixes 65a206c01e8e ("net/sched: Change act_api and act_xxx modules to use IDR")
---
 net/sched/act_bpf.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_bpf.c +1 -1
index b3f2c15affa7..9d2cabf1dc7e 100644
@@ -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
#2 lore raw

PATCH v2 2/7 net/sched: fix idr leak in the error path of tcf_simp_init()

In reply to Davide Caratti

if 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().

Fixes 65a206c01e8e ("net/sched: Change act_api and act_xxx modules to use IDR")
---
 net/sched/act_simple.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_simple.c +1 -1
index 425eac11f6da..b1f38063ada0 100644
@@ -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
#3 lore raw

PATCH v2 3/7 net/sched: fix idr leak in the error path of tcf_act_police_init()

In reply to Davide Caratti

tcf_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().

Fixes 65a206c01e8e ("net/sched: Change act_api and act_xxx modules to use IDR")
---
 net/sched/act_police.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_police.c +1 -1
index 95d3c9097b25..faebf82b99f1 100644
@@ -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
#4 lore raw

PATCH v2 4/7 net/sched: fix idr leak in the error path of tcp_pedit_init()

In reply to Davide Caratti

tcf_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().

Fixes 65a206c01e8e ("net/sched: Change act_api and act_xxx modules to use IDR")
---
 net/sched/act_pedit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_pedit.c +1 -1
index 349beaffb29e..fef08835f26d 100644
@@ -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
#5 lore raw

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.

Fixes 65a206c01e8e ("net/sched: Change act_api and act_xxx modules to use IDR")
---
 net/sched/act_ipt.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)
net/sched/act_ipt.c +6 -3
index 06e380ae0928..7e06b9b62613 100644
@@ -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
#6 lore raw

PATCH v2 6/7 net/sched: fix idr leak in the error path of tcf_vlan_init()

In reply to Davide Caratti

tcf_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
Fixes 4c5b9d9642c8 ("act_vlan: VLAN action rewrite to use RCU lock/unlock and update")
Fixes 65a206c01e8e ("net/sched: Change act_api and act_xxx modules to use IDR")
---
 net/sched/act_vlan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_vlan.c +1 -1
index c2914e9a4a6f..c49cb61adedf 100644
@@ -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
#7 lore raw

PATCH v2 7/7 net/sched: fix idr leak in the error path of tcf_skbmod_init()

In reply to Davide Caratti

tcf_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
Fixes 65a206c01e8e ("net/sched: Change act_api and act_xxx modules to use IDR")
---
 net/sched/act_skbmod.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/act_skbmod.c +1 -1
index d09565d6433e..7b0700f52b50 100644
@@ -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
Acked-by on the v2 series
#8 lore raw
In reply to Davide Caratti
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.

maintainer
#9 lore raw
In reply to Davide Caratti

From: 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.