From: Markus Elfring <elfring@xxxxxxxxxxxxxxxxxxxxx> Date: Sat, 30 Dec 2023 20:28:11 +0100 The kfree() function was called in some cases by the trie_update_elem() function during error handling even if the passed variable contained a null pointer. This issue was detected by using the Coccinelle software. * Thus adjust jump targets. * Reorder data processing steps at the end. * Delete an initialisation (for the variable “new_node”) and a repeated pointer check which became unnecessary with this refactoring. Signed-off-by: Markus Elfring <elfring@xxxxxxxxxxxxxxxxxxxxx> --- kernel/bpf/lpm_trie.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c index b32be680da6c..6c372d831d0f 100644 --- a/kernel/bpf/lpm_trie.c +++ b/kernel/bpf/lpm_trie.c @@ -307,7 +307,7 @@ static long trie_update_elem(struct bpf_map *map, void *_key, void *value, u64 flags) { struct lpm_trie *trie = container_of(map, struct lpm_trie, map); - struct lpm_trie_node *node, *im_node = NULL, *new_node = NULL; + struct lpm_trie_node *node, *im_node = NULL, *new_node; struct lpm_trie_node __rcu **slot; struct bpf_lpm_trie_key *key = _key; unsigned long irq_flags; @@ -327,13 +327,13 @@ static long trie_update_elem(struct bpf_map *map, if (trie->n_entries == trie->map.max_entries) { ret = -ENOSPC; - goto out; + goto unlock; } new_node = lpm_trie_node_alloc(trie, value); if (!new_node) { ret = -ENOMEM; - goto out; + goto unlock; } trie->n_entries++; @@ -368,7 +368,7 @@ static long trie_update_elem(struct bpf_map *map, */ if (!node) { rcu_assign_pointer(*slot, new_node); - goto out; + goto decrement_counter; } /* If the slot we picked already exists, replace it with @new_node @@ -384,7 +384,7 @@ static long trie_update_elem(struct bpf_map *map, rcu_assign_pointer(*slot, new_node); kfree_rcu(node, rcu); - goto out; + goto decrement_counter; } /* If the new node matches the prefix completely, it must be inserted @@ -394,13 +394,13 @@ static long trie_update_elem(struct bpf_map *map, next_bit = extract_bit(node->data, matchlen); rcu_assign_pointer(new_node->child[next_bit], node); rcu_assign_pointer(*slot, new_node); - goto out; + goto decrement_counter; } im_node = lpm_trie_node_alloc(trie, NULL); if (!im_node) { ret = -ENOMEM; - goto out; + goto decrement_counter; } im_node->prefixlen = matchlen; @@ -419,15 +419,13 @@ static long trie_update_elem(struct bpf_map *map, /* Finally, assign the intermediate node to the determined slot */ rcu_assign_pointer(*slot, im_node); -out: if (ret) { - if (new_node) - trie->n_entries--; - - kfree(new_node); kfree(im_node); +decrement_counter: + trie->n_entries--; + kfree(new_node); } - +unlock: spin_unlock_irqrestore(&trie->lock, irq_flags); return ret; -- 2.43.0