Commit 1e962ba9 authored by Rusty Russell's avatar Rusty Russell

talloc: fixed a use after free error

(Import from SAMBA commit 6f51a1f45bf4de062cce7a562477e8140630a53d):

this is the minimal fix for the problem Rusty found. I previously
thought that the best fix would be to change tc->parent to be valid
for all pointers, but that is expensive for realloc with large numbers
of child pointers, which is much more commmon than I expected it to
be.
parent 87aba1fa
......@@ -538,13 +538,28 @@ static inline int _talloc_free(const void *ptr)
final choice is the null context. */
void *child = TC_PTR_FROM_CHUNK(tc->child);
const void *new_parent = null_context;
struct talloc_chunk *old_parent = NULL;
if (unlikely(tc->child->refs)) {
struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs);
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
/* finding the parent here is potentially quite
expensive, but the alternative, which is to change
talloc to always have a valid tc->parent pointer,
makes realloc more expensive where there are a
large number of children.
The reason we need the parent pointer here is that
if _talloc_free_internal() fails due to references
or a failing destructor we need to re-parent, but
the free call can invalidate the prev pointer.
*/
if (new_parent == null_context && (tc->child->refs || tc->child->destructor)) {
old_parent = talloc_parent_chunk(ptr);
}
if (unlikely(_talloc_free(child) == -1)) {
if (new_parent == null_context) {
struct talloc_chunk *p = talloc_parent_chunk(ptr);
struct talloc_chunk *p = old_parent;
if (p) new_parent = TC_PTR_FROM_CHUNK(p);
}
__talloc_steal(new_parent, child);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment