Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
Closed
Description
Crash report
What happened?
Version
Python 3.14.0a0 (heads/main:34f5ae69fe, Jun 9 2024, 21:27:54) [GCC 11.4.0]
bisect from commit2158977
Root Cause
Thecall_timer function can execute arbitrary code frompObj, which is initialized by the user. If the code calls_lsprof_type_Profiler_post1.disable() in Python, it will hitprofiler_disable in C. Then, theself (ProfileContext) will be freed. Consequently, after call_timer returns,self->t0 will cause a use-after-free error.
staticvoidinitContext(ProfilerObject*pObj,ProfilerContext*self,ProfilerEntry*entry){self->ctxEntry=entry;self->subt=0;self->previous=pObj->currentProfilerContext;pObj->currentProfilerContext=self;++entry->recursionLevel;if ((pObj->flags&POF_SUBCALLS)&&self->previous) {/* find or create an entry for me in my caller's entry */ProfilerEntry*caller=self->previous->ctxEntry;ProfilerSubEntry*subentry=getSubEntry(pObj,caller,entry);if (subentry==NULL)subentry=newSubEntry(pObj,caller,entry);if (subentry)++subentry->recursionLevel; }self->t0=call_timer(pObj);// <-- execute arbitrary code}
POC
import_lsprofclassevil():def__call__(self):_lsprof_type_Profiler_post1.disable()returnTrue_lsprof_type_Profiler_post1=_lsprof.Profiler(evil())_lsprof_type_Profiler_post1.enable()print ("dummy")
ASAN
asan
===================================================================21434==ERROR: AddressSanitizer: heap-use-after-free on address 0x6060000626d0 at pc 0x7f2a7eaa4f22 bp 0x7ffe7a876d30 sp 0x7ffe7a876d20WRITE of size 8 at 0x6060000626d0 thread T0 #0 0x7f2a7eaa4f21 in initContext Modules/_lsprof.c:310 #1 0x7f2a7eaa684f in ptrace_enter_call Modules/_lsprof.c:379 #2 0x7f2a7eaa8098 in ccall_callback Modules/_lsprof.c:653 #3 0x563c6a7ce4da in cfunction_vectorcall_FASTCALL Objects/methodobject.c:425 #4 0x563c6ab10cb2 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:168 #5 0x563c6ab10cb2 in call_one_instrument Python/instrumentation.c:907 #6 0x563c6ab1258b in call_instrumentation_vector Python/instrumentation.c:1095 #7 0x563c6ab1663d in _Py_call_instrumentation_2args Python/instrumentation.c:1150 #8 0x563c6aa2b5c5 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:3229 #9 0x563c6aa4ca7b in _PyEval_EvalFrame Include/internal/pycore_ceval.h:119 #10 0x563c6aa4ca7b in _PyEval_Vector Python/ceval.c:1819 #11 0x563c6aa4cc9c in PyEval_EvalCode Python/ceval.c:599 #12 0x563c6ab64c51 in run_eval_code_obj Python/pythonrun.c:1292 #13 0x563c6ab67b96 in run_mod Python/pythonrun.c:1377 #14 0x563c6ab68976 in pyrun_file Python/pythonrun.c:1210 #15 0x563c6ab6ae55 in _PyRun_SimpleFileObject Python/pythonrun.c:459 #16 0x563c6ab6b349 in _PyRun_AnyFileObject Python/pythonrun.c:77 #17 0x563c6abcc718 in pymain_run_file_obj Modules/main.c:357 #18 0x563c6abcefea in pymain_run_file Modules/main.c:376 #19 0x563c6abcfbfb in pymain_run_python Modules/main.c:639 #20 0x563c6abcfd8b in Py_RunMain Modules/main.c:718 #21 0x563c6abcff72 in pymain_main Modules/main.c:748 #22 0x563c6abd02ea in Py_BytesMain Modules/main.c:772 #23 0x563c6a539b15 in main Programs/python.c:15 #24 0x7f2a81d33d8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) #25 0x7f2a81d33e3f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) #26 0x563c6a539a44 in _start (/home/kcats/cpython/python+0x282a44)0x6060000626d0 is located 16 bytes inside of 56-byte region [0x6060000626c0,0x6060000626f8)freed by thread T0 here: #0 0x7f2a820ce537 in __interceptor_free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:127 #1 0x563c6a7e49c5 in _PyMem_RawFree Objects/obmalloc.c:90 #2 0x563c6a7e6c2f in _PyMem_DebugRawFree Objects/obmalloc.c:2754 #3 0x563c6a7e755d in _PyMem_DebugFree Objects/obmalloc.c:2891 #4 0x563c6a81abad in PyMem_Free Objects/obmalloc.c:1010 #5 0x7f2a7eaa4c21 in flush_unmatched Modules/_lsprof.c:766 #6 0x7f2a7eaa6d4f in profiler_disable Modules/_lsprof.c:815 #7 0x563c6a70183f in method_vectorcall_NOARGS Objects/descrobject.c:447 #8 0x563c6a6d7bb9 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:168 #9 0x563c6a6d7d14 in PyObject_Vectorcall Objects/call.c:327 #10 0x563c6aa148c4 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:813 #11 0x563c6aa4ca7b in _PyEval_EvalFrame Include/internal/pycore_ceval.h:119 #12 0x563c6aa4ca7b in _PyEval_Vector Python/ceval.c:1819 #13 0x563c6a6d720d in _PyFunction_Vectorcall Objects/call.c:413 #14 0x563c6a6dbe79 in _PyObject_VectorcallDictTstate Objects/call.c:135 #15 0x563c6a6dc351 in _PyObject_Call_Prepend Objects/call.c:504 #16 0x563c6a876cc8 in slot_tp_call Objects/typeobject.c:9668 #17 0x563c6a6d75e7 in _PyObject_MakeTpCall Objects/call.c:242 #18 0x7f2a7eaa452d in _PyObject_VectorcallTstate Include/internal/pycore_call.h:166 #19 0x7f2a7eaa452d in _PyObject_CallNoArgs Include/internal/pycore_call.h:184 #20 0x7f2a7eaa452d in CallExternalTimer Modules/_lsprof.c:90 #21 0x7f2a7eaa4e1c in call_timer Modules/_lsprof.c:121 #22 0x7f2a7eaa4e1c in initContext Modules/_lsprof.c:310 #23 0x7f2a7eaa684f in ptrace_enter_call Modules/_lsprof.c:379 #24 0x7f2a7eaa8098 in ccall_callback Modules/_lsprof.c:653 #25 0x563c6a7ce4da in cfunction_vectorcall_FASTCALL Objects/methodobject.c:425 #26 0x563c6ab10cb2 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:168 #27 0x563c6ab10cb2 in call_one_instrument Python/instrumentation.c:907 #28 0x563c6ab1258b in call_instrumentation_vector Python/instrumentation.c:1095 #29 0x563c6ab1663d in _Py_call_instrumentation_2args Python/instrumentation.c:1150 #30 0x563c6aa2b5c5 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:3229 #31 0x563c6aa4ca7b in _PyEval_EvalFrame Include/internal/pycore_ceval.h:119 #32 0x563c6aa4ca7b in _PyEval_Vector Python/ceval.c:1819 #33 0x563c6aa4cc9c in PyEval_EvalCode Python/ceval.c:599 #34 0x563c6ab64c51 in run_eval_code_obj Python/pythonrun.c:1292 #35 0x563c6ab67b96 in run_mod Python/pythonrun.c:1377previously allocated by thread T0 here: #0 0x7f2a820ce887 in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:145 #1 0x563c6a7e556c in _PyMem_RawMalloc Objects/obmalloc.c:62 #2 0x563c6a7e489f in _PyMem_DebugRawAlloc Objects/obmalloc.c:2686 #3 0x563c6a7e4907 in _PyMem_DebugRawMalloc Objects/obmalloc.c:2719 #4 0x563c6a7e759f in _PyMem_DebugMalloc Objects/obmalloc.c:2876 #5 0x563c6a81aa69 in PyMem_Malloc Objects/obmalloc.c:981 #6 0x7f2a7eaa6892 in ptrace_enter_call Modules/_lsprof.c:373 #7 0x7f2a7eaa8098 in ccall_callback Modules/_lsprof.c:653 #8 0x563c6a7ce4da in cfunction_vectorcall_FASTCALL Objects/methodobject.c:425 #9 0x563c6ab10cb2 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:168 #10 0x563c6ab10cb2 in call_one_instrument Python/instrumentation.c:907 #11 0x563c6ab1258b in call_instrumentation_vector Python/instrumentation.c:1095 #12 0x563c6ab1663d in _Py_call_instrumentation_2args Python/instrumentation.c:1150 #13 0x563c6aa2b5c5 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:3229 #14 0x563c6aa4ca7b in _PyEval_EvalFrame Include/internal/pycore_ceval.h:119 #15 0x563c6aa4ca7b in _PyEval_Vector Python/ceval.c:1819 #16 0x563c6aa4cc9c in PyEval_EvalCode Python/ceval.c:599 #17 0x563c6ab64c51 in run_eval_code_obj Python/pythonrun.c:1292 #18 0x563c6ab67b96 in run_mod Python/pythonrun.c:1377 #19 0x563c6ab68976 in pyrun_file Python/pythonrun.c:1210 #20 0x563c6ab6ae55 in _PyRun_SimpleFileObject Python/pythonrun.c:459 #21 0x563c6ab6b349 in _PyRun_AnyFileObject Python/pythonrun.c:77 #22 0x563c6abcc718 in pymain_run_file_obj Modules/main.c:357 #23 0x563c6abcefea in pymain_run_file Modules/main.c:376 #24 0x563c6abcfbfb in pymain_run_python Modules/main.c:639 #25 0x563c6abcfd8b in Py_RunMain Modules/main.c:718 #26 0x563c6abcff72 in pymain_main Modules/main.c:748 #27 0x563c6abd02ea in Py_BytesMain Modules/main.c:772 #28 0x563c6a539b15 in main Programs/python.c:15 #29 0x7f2a81d33d8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f)SUMMARY: AddressSanitizer: heap-use-after-free Modules/_lsprof.c:310 in initContextShadow bytes around the buggy address: 0x0c0c80004480: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa 0x0c0c80004490: 00 00 00 00 00 00 00 fa fa fa fa fa fd fd fd fd 0x0c0c800044a0: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fa 0x0c0c800044b0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa 0x0c0c800044c0: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd=>0x0c0c800044d0: fd fd fd fa fa fa fa fa fd fd[fd]fd fd fd fd fa 0x0c0c800044e0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa 0x0c0c800044f0: fd fd fd fd fd fd fd fa fa fa fa fa fd fd fd fd 0x0c0c80004500: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fa 0x0c0c80004510: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0c80004520: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa faShadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc==21434==ABORTINGCPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.14.0a0 (heads/main:34f5ae69fe, Jun 9 2024, 21:27:54) [GCC 11.4.0]
Linked PRs
- gh-120289: Do not free memory in disable() to prevent use-after-free #120297
- [3.13] gh-120289: Disallow disable() and clear() in external timer to prevent use-after-free (GH-120297) #121984
- [3.12] gh-120289: Disallow disable() and clear() in external timer to prevent use-after-free (GH-120297) #121989
- gh-120289: Add external timer in traverse of _lsprof.Profiler #121998
- [3.13] gh-120289: Add external timer in traverse of _lsprof.Profiler (GH-121998) #122000
- [3.12] gh-120289: Add external timer in traverse of _lsprof.Profiler (GH-121998) #122001