[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <000000000000dd9c39060bfac1fb@google.com>
Date: Thu, 07 Dec 2023 23:44:42 -0800
From: syzbot <syzbot+006987d1be3586e13555@...kaller.appspotmail.com>
To: linux-kernel@...r.kernel.org
Subject: Re: [syzbot] [arm-msm?] [net?] memory leak in radix_tree_insert
For archival purposes, forwarding an incoming command email to
linux-kernel@...r.kernel.org.
***
Subject: [arm-msm?] [net?] memory leak in radix_tree_insert
Author: lizhi.xu@...driver.com
#syz test https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 33cc938e65a9
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index 976b9bd02a1b..5c2f9d8f2c3e 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -581,6 +579,24 @@ static bool delete_node(struct radix_tree_root *root,
return deleted;
}
+static bool __radix_tree_delete(struct radix_tree_root *root,
+ struct radix_tree_node *node, void __rcu **slot)
+{
+ void *old = rcu_dereference_raw(*slot);
+ int values = xa_is_value(old) ? -1 : 0;
+ unsigned offset = get_slot_offset(node, slot);
+ int tag;
+
+ if (is_idr(root))
+ node_tag_set(root, node, IDR_FREE, offset);
+ else
+ for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++)
+ node_tag_clear(root, node, tag, offset);
+
+ replace_slot(slot, NULL, node, -1, values);
+ return node && delete_node(root, node);
+}
+
/**
* __radix_tree_create - create a slot in a radix tree
* @root: radix tree root
@@ -714,8 +714,10 @@ int radix_tree_insert(struct radix_tree_root *root, unsigned long index,
return error;
error = insert_entries(node, slot, item);
- if (error < 0)
+ if (error < 0) {
+ __radix_tree_delete(root, node, slot);
return error;
+ }
if (node) {
unsigned offset = get_slot_offset(node, slot);
@@ -1365,24 +1381,6 @@ radix_tree_gang_lookup_tag_slot(const struct radix_tree_root *root,
}
EXPORT_SYMBOL(radix_tree_gang_lookup_tag_slot);
-static bool __radix_tree_delete(struct radix_tree_root *root,
- struct radix_tree_node *node, void __rcu **slot)
-{
- void *old = rcu_dereference_raw(*slot);
- int values = xa_is_value(old) ? -1 : 0;
- unsigned offset = get_slot_offset(node, slot);
- int tag;
-
- if (is_idr(root))
- node_tag_set(root, node, IDR_FREE, offset);
- else
- for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++)
- node_tag_clear(root, node, tag, offset);
-
- replace_slot(slot, NULL, node, -1, values);
- return node && delete_node(root, node);
-}
-
/**
* radix_tree_iter_delete - delete the entry at this iterator position
* @root: radix tree root
Powered by blists - more mailing lists