Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Heap UAF in io.TextIOWrapper read path via reentrant detach() #157363

Description

@djarfluka

Bug description:

import io

class RAW(io.RawIOBase):
    def readable(self):
        return True
    def readinto(self, b):
        tw.detach()        
        b[:3] = b"abc"
        return 3

tw = io.TextIOWrapper(io.BufferedReader(RAW()), encoding="utf-8")
tw.read()
Exception ignored while finalizing file <_io.BufferedReader>:
Traceback (most recent call last):
  File "/repro/audit4/repro/textio_detach_uaf.py", line 21, in readinto
    tw.detach()
    ~~~~~~~~~^^
RuntimeError: reentrant call inside <_io.BufferedReader>
=================================================================
==1==ERROR: AddressSanitizer: heap-use-after-free on address 0x50f000039ff0 at pc 0xaaaad92e3ca4 bp 0xffffeddd0980 sp 0xffffeddd0970
WRITE of size 8 at 0x50f000039ff0 thread T0
    #0 0xaaaad92e3ca0 in _io__Buffered_read_impl Modules/_io/bufferedio.c:1022
    #1 0xaaaad92e3ca0 in _io__Buffered_read Modules/_io/clinic/bufferedio.c.h:677
    #2 0xaaaad8869b50 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #3 0xaaaad8869b50 in PyObject_VectorcallMethod Objects/call.c:921
    #4 0xaaaad92eb514 in PyObject_CallMethodNoArgs Include/cpython/abstract.h:65
    #5 0xaaaad92eb514 in buffer_callmethod_noargs Modules/_io/textio.c:781
    #6 0xaaaad93061e8 in _io_TextIOWrapper_read_impl Modules/_io/textio.c:2083
    #7 0xaaaad93061e8 in _io_TextIOWrapper_read Modules/_io/clinic/textio.c.h:857
    #8 0xaaaad8866320 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #9 0xaaaad8866320 in PyObject_Vectorcall Objects/call.c:327
    #10 0xaaaad8eb1bc8 in _Py_VectorCallInstrumentation_StackRefSteal Python/ceval.c:768
    #11 0xaaaad85e1de8 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1906
    #12 0xaaaad8ed0b1c in _PyEval_EvalFrame Include/internal/pycore_ceval.h:122
    #13 0xaaaad8ed0b1c in _PyEval_Vector Python/ceval.c:2174
    #14 0xaaaad8ed0b1c in PyEval_EvalCode Python/ceval.c:679
    #15 0xaaaad90cfeb4 in run_mod Python/pythonrun.c:1509
    #16 0xaaaad90d0d38 in _PyRun_File Python/pythonrun.c:1332
    #17 0xaaaad90d4ffc in _PyRun_SimpleFile Python/pythonrun.c:544
    #18 0xaaaad90d8dd0 in _PyRun_AnyFile Python/pythonrun.c:92
    #19 0xaaaad91a390c in pymain_run_file_obj Modules/main.c:478
    #20 0xaaaad91a390c in pymain_run_file Modules/main.c:494
    #21 0xaaaad91a390c in pymain_run_python Modules/main.c:804
    #22 0xaaaad91a390c in Py_RunMain Modules/main.c:891
    #23 0xaaaad91a5c38 in pymain_main Modules/main.c:921
    #24 0xaaaad91a5c38 in Py_BytesMain Modules/main.c:945
    #25 0xffff9b6684c0  (/lib/aarch64-linux-gnu/libc.so.6+0x284c0) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #26 0xffff9b668594 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28594) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #27 0xaaaad864beec in _start (/src/cpython/python+0x183beec) (BuildId: eba909a3db0adabacf151d7dc3081dda7999191a)

0x50f000039ff0 is located 128 bytes inside of 168-byte region [0x50f000039f70,0x50f00003a018)
freed by thread T0 here:
    #0 0xffff9c0061b4 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0xaaaad92cd8dc in buffered_dealloc Modules/_io/bufferedio.c:444
    #2 0xaaaad8a57ab0 in _Py_Dealloc Objects/object.c:3334
    #3 0xaaaad860fea0 in Py_DECREF_MORTAL Include/internal/pycore_object.h:449
    #4 0xaaaad860fea0 in PyStackRef_XCLOSE Include/internal/pycore_stackref.h:726
    #5 0xaaaad860fea0 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:11163
    #6 0xaaaad8ed1a00 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:122
    #7 0xaaaad8ed1a00 in _PyEval_Vector Python/ceval.c:2174
    #8 0xaaaad8864e58 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #9 0xaaaad8864e58 in object_vacall Objects/call.c:823
    #10 0xaaaad886a2c8 in PyObject_CallMethodObjArgs Objects/call.c:960
    #11 0xaaaad92b253c in _io__RawIOBase_read_impl Modules/_io/iobase.c:936
    #12 0xaaaad92b253c in _io__RawIOBase_read Modules/_io/clinic/iobase.c.h:425
    #13 0xaaaad8865880 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #14 0xaaaad8865880 in _PyObject_CallFunctionVa Objects/call.c:552
    #15 0xaaaad8867aa0 in callmethod Objects/call.c:626
    #16 0xaaaad8867aa0 in _PyObject_CallMethod Objects/call.c:694
    #17 0xaaaad92b1cec in _io__RawIOBase_readall_impl Modules/_io/iobase.c:979
    #18 0xaaaad92b1cec in _io__RawIOBase_readall Modules/_io/clinic/iobase.c.h:446
    #19 0xaaaad92e2d88 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #20 0xaaaad92e2d88 in _PyObject_CallNoArgs Include/internal/pycore_call.h:160
    #21 0xaaaad92e2d88 in _bufferedreader_read_all Modules/_io/bufferedio.c:1717
    #22 0xaaaad92e2d88 in _io__Buffered_read_impl Modules/_io/bufferedio.c:1010
    #23 0xaaaad92e2d88 in _io__Buffered_read Modules/_io/clinic/bufferedio.c.h:677
    #24 0xaaaad8869b50 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #25 0xaaaad8869b50 in PyObject_VectorcallMethod Objects/call.c:921
    #26 0xaaaad92eb514 in PyObject_CallMethodNoArgs Include/cpython/abstract.h:65
    #27 0xaaaad92eb514 in buffer_callmethod_noargs Modules/_io/textio.c:781
    #28 0xaaaad93061e8 in _io_TextIOWrapper_read_impl Modules/_io/textio.c:2083
    #29 0xaaaad93061e8 in _io_TextIOWrapper_read Modules/_io/clinic/textio.c.h:857
    #30 0xaaaad8866320 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #31 0xaaaad8866320 in PyObject_Vectorcall Objects/call.c:327
    #32 0xaaaad8eb1bc8 in _Py_VectorCallInstrumentation_StackRefSteal Python/ceval.c:768
    #33 0xaaaad85e1de8 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1906
    #34 0xaaaad8ed0b1c in _PyEval_EvalFrame Include/internal/pycore_ceval.h:122
    #35 0xaaaad8ed0b1c in _PyEval_Vector Python/ceval.c:2174
    #36 0xaaaad8ed0b1c in PyEval_EvalCode Python/ceval.c:679
    #37 0xaaaad90cfeb4 in run_mod Python/pythonrun.c:1509
    #38 0xaaaad90d0d38 in _PyRun_File Python/pythonrun.c:1332
    #39 0xaaaad90d4ffc in _PyRun_SimpleFile Python/pythonrun.c:544
    #40 0xaaaad90d8dd0 in _PyRun_AnyFile Python/pythonrun.c:92
    #41 0xaaaad91a390c in pymain_run_file_obj Modules/main.c:478
    #42 0xaaaad91a390c in pymain_run_file Modules/main.c:494
    #43 0xaaaad91a390c in pymain_run_python Modules/main.c:804
    #44 0xaaaad91a390c in Py_RunMain Modules/main.c:891
    #45 0xaaaad91a5c38 in pymain_main Modules/main.c:921
    #46 0xaaaad91a5c38 in Py_BytesMain Modules/main.c:945
    #47 0xffff9b6684c0  (/lib/aarch64-linux-gnu/libc.so.6+0x284c0) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #48 0xffff9b668594 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28594) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #49 0xaaaad864beec in _start (/src/cpython/python+0x183beec) (BuildId: eba909a3db0adabacf151d7dc3081dda7999191a)

previously allocated by thread T0 here:
    #0 0xffff9c0076d0 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0xaaaad8b7077c in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46
    #2 0xaaaad8b7077c in _PyType_AllocNoTrack Objects/typeobject.c:2498
    #3 0xaaaad8b70e00 in PyType_GenericAlloc Objects/typeobject.c:2529
    #4 0xaaaad8b76808 in type_call Objects/typeobject.c:2442
    #5 0xaaaad8864250 in _PyObject_MakeTpCall Objects/call.c:242
    #6 0xaaaad8eb1bc8 in _Py_VectorCallInstrumentation_StackRefSteal Python/ceval.c:768
    #7 0xaaaad85e1de8 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1906
    #8 0xaaaad8ed0b1c in _PyEval_EvalFrame Include/internal/pycore_ceval.h:122
    #9 0xaaaad8ed0b1c in _PyEval_Vector Python/ceval.c:2174
    #10 0xaaaad8ed0b1c in PyEval_EvalCode Python/ceval.c:679
    #11 0xaaaad90cfeb4 in run_mod Python/pythonrun.c:1509
    #12 0xaaaad90d0d38 in _PyRun_File Python/pythonrun.c:1332
    #13 0xaaaad90d4ffc in _PyRun_SimpleFile Python/pythonrun.c:544
    #14 0xaaaad90d8dd0 in _PyRun_AnyFile Python/pythonrun.c:92
    #15 0xaaaad91a390c in pymain_run_file_obj Modules/main.c:478
    #16 0xaaaad91a390c in pymain_run_file Modules/main.c:494
    #17 0xaaaad91a390c in pymain_run_python Modules/main.c:804
    #18 0xaaaad91a390c in Py_RunMain Modules/main.c:891
    #19 0xaaaad91a5c38 in pymain_main Modules/main.c:921
    #20 0xaaaad91a5c38 in Py_BytesMain Modules/main.c:945
    #21 0xffff9b6684c0  (/lib/aarch64-linux-gnu/libc.so.6+0x284c0) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #22 0xffff9b668594 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28594) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #23 0xaaaad864beec in _start (/src/cpython/python+0x183beec) (BuildId: eba909a3db0adabacf151d7dc3081dda7999191a)

SUMMARY: AddressSanitizer: heap-use-after-free Modules/_io/bufferedio.c:1022 in _io__Buffered_read_impl
Shadow bytes around the buggy address:
  0x50f000039d00: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
  0x50f000039d80: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x50f000039e00: 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa fa
  0x50f000039e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x50f000039f00: 00 00 00 00 00 fa fa fa fa fa fa fa fa fa fd fd
=>0x50f000039f80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd
  0x50f00003a000: fd fd fd fa fa fa fa fa fa fa fa fa fd fd fd fd
  0x50f00003a080: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x50f00003a100: fd fa fa fa fa fa fa fa fa fa fd fd fd fd fd fd
  0x50f00003a180: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
  0x50f00003a200: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
Shadow 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
==1==ABORTING

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions