New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
deque.index() overruns deque boundary #69101
Comments
Python 3.5 suffers from a vulnerability caused by the behavior of the newblock() function used by the collections.deque module. When called, newblock() allocates memory using PyMem_Malloc() and does not initialize it: static block *
newblock(Py_ssize_t len) {
block *b;
if (len >= MAX_DEQUE_LEN) {
PyErr_SetString(PyExc_OverflowError,
"cannot add more blocks to the deque");
return NULL;
}
if (numfreeblocks) {
numfreeblocks--;
return freeblocks[numfreeblocks];
}
b = PyMem_Malloc(sizeof(block)); <<<< Memory allocation.
if (b != NULL) {
return b; <<<< Buffer returned without initialization.
}
PyErr_NoMemory();
return NULL;
} Because PyMem_Malloc does not initialize the memory, the block may contain garbage data. In some cases, this can lead to memory corruption which could be exploitable to achieve code execution. The following exception analysis is an example of EIP corruption:
*** The OS name list needs to be updated! Unknown Windows version: 10.0 *** FAULTING_IP: EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) CONTEXT: 0000000 -- (.cxr 0x0;r) PROCESS_NAME: pythonw.exe ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s. EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s. EXCEPTION_PARAMETER1: 00000008 EXCEPTION_PARAMETER2: 696f60d8 WRITE_ADDRESS: 696f60d8 FOLLOWUP_IP: FAILED_INSTRUCTION_ADDRESS: APP: pythonw.exe ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre FAULTING_THREAD: 000009dc DEFAULT_BUCKET_ID: SOFTWARE_NX_FAULT_CODE PRIMARY_PROBLEM_CLASS: SOFTWARE_NX_FAULT_CODE BUGCHECK_STR: APPLICATION_FAULT_SOFTWARE_NX_FAULT_CODE_SOFTWARE_NX_FAULT_FALSE_POSITIVE LAST_CONTROL_TRANSFER: from 69505ad3 to 696f60d8 STACK_TEXT: STACK_COMMAND: ~0s; .ecxr ; kb SYMBOL_STACK_INDEX: 0 SYMBOL_NAME: python35!PyUnicode_Type+0 FOLLOWUP_NAME: MachineOwner MODULE_NAME: python35 IMAGE_NAME: python35.dll DEBUG_FLR_IMAGE_TIMESTAMP: 5598ccc2 FAILURE_BUCKET_ID: SOFTWARE_NX_FAULT_CODE_c0000005_python35.dll!PyUnicode_Type BUCKET_ID: APPLICATION_FAULT_SOFTWARE_NX_FAULT_CODE_SOFTWARE_NX_FAULT_FALSE_POSITIVE_BAD_IP_python35!PyUnicode_Type+0 ANALYSIS_SOURCE: UM FAILURE_ID_HASH_STRING: um:software_nx_fault_code_c0000005_python35.dll!pyunicode_type FAILURE_ID_HASH: {aa94d074-8f9b-b618-df4f-eaad15f84370} Followup: MachineOwner To fix the issue, it is recommended that newblock use PyMem_Calloc instead of PyMem_Malloc. A proposed patch has been attached. Credit: John Leitch (johnleitch@outlook.com), Bryce Darling (darlingbryce@gmail.com) |
I'm find the "exception analysis" to be unreadable. Have you found any place in the deque code where the uninitialized memory actually gets accessed? |
The "exception analysis" is output from the WinDbg !analyze command run on a crash where access to the uninitialized memory ultimately corrupted the instruction pointer, leading to a data execution prevention crash. That's why the disassembly is junk--the IP is not pointing to valid instructions. This crash was provided as an example because it demonstrates that the issue is likely exploitable, and can probably be used to achieve code execution. Here is an example of a crash where execution halts immediately upon attempted to dereference a corrupted pointer. Note that the pointer is 0xC0C0C0C0--a fill pattern indicative of uninitialized memory. 0:000> r
FAULTING_IP: EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) CONTEXT: 0000000 -- (.cxr 0x0;r) FAULTING_THREAD: 00004a48 DEFAULT_BUCKET_ID: INVALID_POINTER_READ PROCESS_NAME: python.exe ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s. EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%p referenced memory at 0x%p. The memory could not be %s. EXCEPTION_PARAMETER1: 0000000 EXCEPTION_PARAMETER2: c0c0c0c4 READ_ADDRESS: c0c0c0c4 FOLLOWUP_IP: NTGLOBALFLAG: 2000000 APPLICATION_VERIFIER_FLAGS: 0 APP: python.exe ANALYSIS_VERSION: 6.3.9600.17029 (debuggers(dbg).140219-1702) x86fre PRIMARY_PROBLEM_CLASS: INVALID_POINTER_READ BUGCHECK_STR: APPLICATION_FAULT_INVALID_POINTER_READ LAST_CONTROL_TRANSFER: from 54f25be3 to 54f25a55 STACK_TEXT: STACK_COMMAND: .cxr 0x0 ; kb FAULTING_SOURCE_LINE: c:\build\cpython\objects\object.c FAULTING_SOURCE_FILE: c:\build\cpython\objects\object.c FAULTING_SOURCE_LINE_NUMBER: 659 FAULTING_SOURCE_CODE:
SYMBOL_STACK_INDEX: 0 SYMBOL_NAME: python35!do_richcompare+15 FOLLOWUP_NAME: MachineOwner MODULE_NAME: python35 IMAGE_NAME: python35.dll DEBUG_FLR_IMAGE_TIMESTAMP: 55c83105 FAILURE_BUCKET_ID: INVALID_POINTER_READ_c0000005_python35.dll!do_richcompare BUCKET_ID: APPLICATION_FAULT_INVALID_POINTER_READ_python35!do_richcompare+15 ANALYSIS_SOURCE: UM FAILURE_ID_HASH_STRING: um:invalid_pointer_read_c0000005_python35.dll!do_richcompare FAILURE_ID_HASH: {9d923c37-6c51-89af-91c6-b0039172374e} Followup: MachineOwner |
I guess that in the test case the stop parameter is set to 4 in |
Larry, this may need to go into 3.5 if there is still an opportunity. |
Please create a pull request at your earliest convenience. |
New changeset ae8ec66adc7f by Raymond Hettinger in branch '3.5': |
I'm not sure what that entails. Can you just apply ae8ec66adc7f and take it from here? |
Assigning to Brett, who has agreed to do the merge to 3.5.0 that Raymond has declined to do. |
Thanks Brett :-) |
PR created, Larry. |
Merged. Please do a (null) merge forward into 3.5.1 and 3.6. Thanks! |
New changeset 9f8c59e61594 by Brett Cannon in branch '3.5': New changeset d093d87e449c by Brett Cannon in branch '3.5': New changeset c6e0c29913ec by Brett Cannon in branch 'default': |
OK, that should cover 3.5.0 and then null merge through 3.5 and default. I thus consider my favour to Larry done and Raymond now owes me one. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: