This is an archive of the discontinued LLVM Phabricator instance.

[lldb/Plugins] Fix ScriptedInterface object ptr use-after-free
AbandonedPublic

Authored by mib on Jan 11 2022, 4:41 PM.

Details

Summary

This patch replaces all the ScriptedInterface object instance shared
pointer by a raw pointer. The reason behind the change is that when the
smart pointer gets re-assigned, that triggers calling the default
deleter to the previously pointer object.

However, in this case, the pointed memory was allocated in Python, so
when another object tries to read it, it causes a heap-use-after-free.

By switching to a raw pointer, it prevents lldb from decrementing the
reference counting to 0 and calling the deleter for that object.

rdar://87425859

Signed-off-by: Med Ismail Bennani <medismail.bennani@gmail.com>

Diff Detail

Event Timeline

mib requested review of this revision.Jan 11 2022, 4:41 PM
mib created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptJan 11 2022, 4:41 PM
labath requested changes to this revision.Jan 12 2022, 3:32 AM
labath added a subscriber: labath.
labath added inline comments.
lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
54

This doesn't sound right. This object (StructuredPythonObject instance) is definitely not created by python and will now be leaked. If I correctly understand the problem, the issue is that the this object gets a non-owning reference (the ret_val argument) to the underlying python object, and then frees it as if it was owning it. If that's the case, then the solution is to INCREF it in the constructor (or switch to using a PythonObject wrapper, which will then handle the lifetime management.

You may also be interested in D114722 (which I hope to update soon). It's not _directly_ related to this, but it touches the same parts of the code.

This revision now requires changes to proceed.Jan 12 2022, 3:32 AM
labath added inline comments.Jan 12 2022, 5:52 AM
lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
54

So, as far as I can tell ret_val is an owned reference (in LLDBSwigPythonCreateScriptedThread, it comes from PythonObject.release()). Could it be that something else is freeing (decreffing) the object more times than it should (thereby releasing the references that are supposed to be held here) and this code gets blamed/crashes just because it happens to run last?

JDevlieghere added inline comments.Jan 12 2022, 11:31 AM
lldb/source/Plugins/ScriptInterpreter/Python/ScriptedThreadPythonInterface.cpp
54

Pavel said it better than I would have :-)

mib abandoned this revision.Jan 12 2022, 12:00 PM

Abandoning this in favor of D117139.