[PATCH 5/5] bpf: Improve exception handling in trie_update_elem()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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






[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux