drivers: cpuidle: lpm-levels: Fix untrusted pointer dereference.
The list_for_each macro was not used correctly, where the intermediate
variable would be LIST_POISON, resulting in a untrusted pointer
dereference. Switch to using list_for_each_entry_safe to for safe
removal of a list entry.
Change-Id: I0e0fd5dd9f251b5093d6e9d6335387512ec59249
Signed-off-by: Mahesh Sivasubramanian <msivasub@codeaurora.org>
diff --git a/drivers/cpuidle/lpm-levels-of.c b/drivers/cpuidle/lpm-levels-of.c
index fec75b1..61c0ae8 100644
--- a/drivers/cpuidle/lpm-levels-of.c
+++ b/drivers/cpuidle/lpm-levels-of.c
@@ -739,26 +739,22 @@ static int parse_cpu_levels(struct device_node *node, struct lpm_cluster *c)
void free_cluster_node(struct lpm_cluster *cluster)
{
- struct list_head *list;
struct lpm_cpu *cpu, *n;
- int i;
+ struct lpm_cluster *cl, *m;
- list_for_each(list, &cluster->child) {
- struct lpm_cluster *n;
-
- n = list_entry(list, typeof(*n), list);
- list_del(list);
- free_cluster_node(n);
+ list_for_each_entry_safe(cl, m, &cluster->child, list) {
+ list_del(&cl->list);
+ free_cluster_node(cl);
};
list_for_each_entry_safe(cpu, n, &cluster->cpu, list) {
- struct lpm_cpu *cpu = list_entry(list, typeof(*cpu), list);
+ int i;
+ list_del(&cpu->list);
for (i = 0; i < cpu->nlevels; i++) {
kfree(cpu->levels[i].name);
cpu->levels[i].name = NULL;
}
- list_del(list);
}
}