| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
Co-authored-by: Florian Mayer <fmayer@google.com> Co-authored-by: Anna <araslanova.anna.a@gmail.com>
Documentation build overview132 files changed · + 8 added · ± 124 modified + Added
± Modified |
Sorry, something went wrong.
|
lgtm |
Sorry, something went wrong.
|
Hi. You asked me to review this change, but I don't know how to test it manually. Can you provide a way to introduce a bug on purpose and explain how to test that HWASAN detects it properly? |
Sorry, something went wrong.
| Note that on x86-64 this uses `page aliasing | ||
| <https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#supported-architectures>`_, | ||
| which only tags heap allocations and is unsafe for programs that ``fork()``, | ||
| including much of the test suite. |
There was a problem hiding this comment.
Do you know which GCC and clang versions added support for this sanitizer?
Sorry, something went wrong.
There was a problem hiding this comment.
LLVM (the reference implementation) supports it on AArch64, and additionally on x86-64 since LLVM 13 with page aliasing. GCC supports it only on AArch64, since GCC 11.
Sorry, something went wrong.
Hi, thanks for the review! If you mean just a trivial example, try for example applying this patch which adds a little heap-use-after-free: diff --git a/Modules/zlibmodule.c b/Modules/zlibmodule.c
index a7fefb1fec5..e7fe3131052 100644
--- a/Modules/zlibmodule.c
+++ b/Modules/zlibmodule.c
@@ -1987,6 +1987,9 @@ static unsigned int
zlib_crc32_impl(PyObject *module, Py_buffer *data, unsigned int value)
/*[clinic end generated code: output=b217562e4fe6d6a6 input=1229cb2fb5ea948a]*/
{
+ volatile char *probe = PyMem_RawMalloc(1);
+ PyMem_RawFree((void *)probe);
+ *probe = '\0';
/* Releasing the GIL for very small buffers is inefficient
and may lower performance */
if (data->len > 1024*5) {Then compile Python with the flag: ./configure --with-hwaddress-sanitizer make -j16 And run: $ ./python -c 'import zlib; zlib.crc32(b"x")' Which for me results in: ==129189==ERROR: HWAddressSanitizer: tag-mismatch on address 0x6802000005c0 at pc 0x000000404d5a
WRITE of size 1 at 0x6802000005c0 tags: 05/1f (ptr/mem) in thread T0
#0 0x000000404d5a in __hwasan_store1 (/home/stan/dev/cpython/python+0x404d5a) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)
#1 0x7fdd1072f973 in zlib_crc32_impl /home/stan/dev/cpython/./Modules/zlibmodule.c:1992:12
#2 0x7fdd1072f973 in zlib_crc32 /home/stan/dev/cpython/./Modules/clinic/zlibmodule.c.h:1285:21
#3 0x0000004e3573 in _PyObject_VectorcallTstate /home/stan/dev/cpython/./Include/internal/pycore_call.h:144:11
#4 0x0000004e3573 in PyObject_Vectorcall /home/stan/dev/cpython/Objects/call.c:327:12
#5 0x0000006a51ff in _Py_VectorCallInstrumentation_StackRefSteal /home/stan/dev/cpython/Python/ceval.c:768:11
#6 0x0000006aa214 in _PyEval_EvalFrameDefault /home/stan/dev/cpython/Python/generated_cases.c.h:1906:35
#7 0x0000006a4248 in _PyEval_EvalFrame /home/stan/dev/cpython/./Include/internal/pycore_ceval.h:122:16
#8 0x0000006a4248 in _PyEval_Vector /home/stan/dev/cpython/Python/ceval.c:2172:12
#9 0x0000006a4248 in PyEval_EvalCode /home/stan/dev/cpython/Python/ceval.c:679:21
#10 0x0000007642ac in run_mod /home/stan/dev/cpython/Python/pythonrun.c:1509:19
#11 0x000000762316 in _PyRun_String /home/stan/dev/cpython/Python/pythonrun.c:1292:15
#12 0x0000007621a6 in _PyRun_SimpleString /home/stan/dev/cpython/Python/pythonrun.c:590:21
#13 0x00000079a3d9 in pymain_run_command /home/stan/dev/cpython/Modules/main.c:308:18
#14 0x00000079a3d9 in pymain_run_python /home/stan/dev/cpython/Modules/main.c:795:21
#15 0x00000079a3d9 in Py_RunMain /home/stan/dev/cpython/Modules/main.c:891:5
#16 0x00000079a7cc in pymain_main /home/stan/dev/cpython/Modules/main.c:921:12
#17 0x00000079a8fb in Py_BytesMain /home/stan/dev/cpython/Modules/main.c:945:12
#18 0x7fdd10bfb5b4 in __libc_start_call_main (/lib64/libc.so.6+0x35b4) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
#19 0x7fdd10bfb667 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3667) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
#20 0x000000402c54 in _start (/home/stan/dev/cpython/python+0x402c54) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)
[0x6802000005c0,0x6802000005d0) is a small unallocated heap chunk; size: 16 offset: 0
Cause: use-after-free
0x6802000005c0 is located 0 bytes inside a 1-byte region [0x6802000005c0,0x6802000005c1)
freed by thread T0 here:
#0 0x00000040c16b in free (/home/stan/dev/cpython/python+0x40c16b) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)
#1 0x7fdd1072f96b in zlib_crc32_impl /home/stan/dev/cpython/./Modules/zlibmodule.c:1991:5
#2 0x7fdd1072f96b in zlib_crc32 /home/stan/dev/cpython/./Modules/clinic/zlibmodule.c.h:1285:21
#3 0x0000004e3573 in _PyObject_VectorcallTstate /home/stan/dev/cpython/./Include/internal/pycore_call.h:144:11
#4 0x0000004e3573 in PyObject_Vectorcall /home/stan/dev/cpython/Objects/call.c:327:12
#5 0x0000006a51ff in _Py_VectorCallInstrumentation_StackRefSteal /home/stan/dev/cpython/Python/ceval.c:768:11
#6 0x0000006aa214 in _PyEval_EvalFrameDefault /home/stan/dev/cpython/Python/generated_cases.c.h:1906:35
#7 0x0000006a4248 in _PyEval_EvalFrame /home/stan/dev/cpython/./Include/internal/pycore_ceval.h:122:16
#8 0x0000006a4248 in _PyEval_Vector /home/stan/dev/cpython/Python/ceval.c:2172:12
#9 0x0000006a4248 in PyEval_EvalCode /home/stan/dev/cpython/Python/ceval.c:679:21
#10 0x0000007642ac in run_mod /home/stan/dev/cpython/Python/pythonrun.c:1509:19
#11 0x000000762316 in _PyRun_String /home/stan/dev/cpython/Python/pythonrun.c:1292:15
#12 0x0000007621a6 in _PyRun_SimpleString /home/stan/dev/cpython/Python/pythonrun.c:590:21
#13 0x00000079a3d9 in pymain_run_command /home/stan/dev/cpython/Modules/main.c:308:18
#14 0x00000079a3d9 in pymain_run_python /home/stan/dev/cpython/Modules/main.c:795:21
#15 0x00000079a3d9 in Py_RunMain /home/stan/dev/cpython/Modules/main.c:891:5
#16 0x00000079a7cc in pymain_main /home/stan/dev/cpython/Modules/main.c:921:12
#17 0x00000079a8fb in Py_BytesMain /home/stan/dev/cpython/Modules/main.c:945:12
#18 0x7fdd10bfb5b4 in __libc_start_call_main (/lib64/libc.so.6+0x35b4) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
#19 0x7fdd10bfb667 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3667) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
#20 0x000000402c54 in _start (/home/stan/dev/cpython/python+0x402c54) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)
previously allocated by thread T0 here:
#0 0x00000040c888 in malloc (/home/stan/dev/cpython/python+0x40c888) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)
#1 0x7fdd1072f960 in zlib_crc32_impl /home/stan/dev/cpython/./Modules/zlibmodule.c:1990:28
#2 0x7fdd1072f960 in zlib_crc32 /home/stan/dev/cpython/./Modules/clinic/zlibmodule.c.h:1285:21
#3 0x0000004e3573 in _PyObject_VectorcallTstate /home/stan/dev/cpython/./Include/internal/pycore_call.h:144:11
#4 0x0000004e3573 in PyObject_Vectorcall /home/stan/dev/cpython/Objects/call.c:327:12
#5 0x0000006a51ff in _Py_VectorCallInstrumentation_StackRefSteal /home/stan/dev/cpython/Python/ceval.c:768:11
#6 0x0000006aa214 in _PyEval_EvalFrameDefault /home/stan/dev/cpython/Python/generated_cases.c.h:1906:35
#7 0x0000006a4248 in _PyEval_EvalFrame /home/stan/dev/cpython/./Include/internal/pycore_ceval.h:122:16
#8 0x0000006a4248 in _PyEval_Vector /home/stan/dev/cpython/Python/ceval.c:2172:12
#9 0x0000006a4248 in PyEval_EvalCode /home/stan/dev/cpython/Python/ceval.c:679:21
#10 0x0000007642ac in run_mod /home/stan/dev/cpython/Python/pythonrun.c:1509:19
#11 0x000000762316 in _PyRun_String /home/stan/dev/cpython/Python/pythonrun.c:1292:15
#12 0x0000007621a6 in _PyRun_SimpleString /home/stan/dev/cpython/Python/pythonrun.c:590:21
#13 0x00000079a3d9 in pymain_run_command /home/stan/dev/cpython/Modules/main.c:308:18
#14 0x00000079a3d9 in pymain_run_python /home/stan/dev/cpython/Modules/main.c:795:21
#15 0x00000079a3d9 in Py_RunMain /home/stan/dev/cpython/Modules/main.c:891:5
#16 0x00000079a7cc in pymain_main /home/stan/dev/cpython/Modules/main.c:921:12
#17 0x00000079a8fb in Py_BytesMain /home/stan/dev/cpython/Modules/main.c:945:12
#18 0x7fdd10bfb5b4 in __libc_start_call_main (/lib64/libc.so.6+0x35b4) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
#19 0x7fdd10bfb667 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x3667) (BuildId: 4586895ddf125800fcd0df1f77ad693eac681450)
#20 0x000000402c54 in _start (/home/stan/dev/cpython/python+0x402c54) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d)
hwasan_dev_note_heap_rb_distance: 1 1023
hwasan_dev_note_num_matching_addrs: 0
hwasan_dev_note_num_matching_addrs_4b: 0
Thread: T0 0x5fff00002000 stack: [0x7ffc35499000,0x7ffc35c99000) sz: 8388608 tls: [0x7fdd10bf6c00,0x7fdd10bf7d00)
Memory tags around the buggy address (one tag corresponds to 16 bytes):
0x6801fffffd00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x6801fffffe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x6801ffffff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x680200000000: 01 0c 06 06 0c 0c 01 08 08 0c 0f 0f 08 07 01 0d
0x680200000100: 0e 0f 01 01 0f 07 0c 0c 0c 0b 0d 01 01 0f 0f 08
0x680200000200: 08 04 0f 04 02 08 08 05 06 09 05 05 06 04 04 03
0x680200000300: 04 04 05 08 04 04 04 07 07 06 07 07 09 07 04 05
0x680200000400: 05 03 06 03 04 03 04 03 06 03 06 01 08 03 01 06
=>0x680200000500: 05 01 03 0f 01 04 01 04 07 77 04 0e [1f] 00 00 00
0x680200000600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x680200000700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x680200000800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x680200000900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x680200000a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x680200000b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x680200000c00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x680200000d00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
0x680200000400: 03 01 06 07 07 06 01 07 02 02 05 02 06 00 05 04
=>0x680200000500: 00 03 00 04 01 00 06 00 00 .. 01 06 [..] .. .. ..
0x680200000600: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
See https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html#short-granules for a description of short granule tags
SUMMARY: HWAddressSanitizer: tag-mismatch (/home/stan/dev/cpython/python+0x404d5a) (BuildId: 0e0c51a83d94ef2780e0f8f6b3eb3cebacd90b1d) in __hwasan_store1
|
Sorry, something went wrong.
Co-authored-by: Victor Stinner <vstinner@python.org>
|
I pushed a commit which incorporates the fix in #157934 for MSan/ASan. |
Sorry, something went wrong.
|
@emmatyping can you please take a look? |
Sorry, something went wrong.
|
Would it be crazy to add an unit test for the test? Add a function in _testcapi which triggers HWASAN (as you shown), and make sure that it fails if HWASAN is used. |
Sorry, something went wrong.
| [x86_64|amd64], [hwasan_flags="$hwasan_flags -fsanitize-hwaddress-experimental-aliasing"] | ||
| ) | ||
| AX_CHECK_COMPILE_FLAG([$hwasan_flags],[ | ||
| BASECFLAGS="$hwasan_flags -fno-omit-frame-pointer $BASECFLAGS" |
There was a problem hiding this comment.
What's the rationale for adding -fno-omit-frame-pointer? Is it required by -fsanitize=hwaddress? Why not putting it in hwasan_flags?
Sorry, something went wrong.
There was a problem hiding this comment.
It isn't required, it's just there for usable stack traces in the reports as the sanitizer runtime uses its frame-pointer-based unwinder for the allocation/free stacks. The --with-address-sanitizer and --with-memory-sanitizer blocks add it for the same reason.
Sorry, something went wrong.
There was a problem hiding this comment.
Oh ok, I didn't notice that it's also used by other sanitizers.
Since PEP 831 in Python 3.15, Python is built with -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer by default, so it should not make a big difference to add -fno-omit-frame-pointer anyway :-)
Sorry, something went wrong.
Sure, I added such a test. It also works under ASan. |
Sorry, something went wrong.
There was a problem hiding this comment.
LGTM. The change looks complete and it's well documented. Thanks to updating libregrtest ;-)
Sorry, something went wrong.
| def check_sanitizer(*, address=False, memory=False, ub=False, thread=False, | ||
| function=True): | ||
| def check_sanitizer(*, address=False, hwaddress=False, memory=False, ub=False, | ||
| thread=False, function=True): |
There was a problem hiding this comment.
That's a long list of sanitizers! 😃 It's cool that we supported all of them!
Sorry, something went wrong.
|
Oh, multiple GitHub Action jobs failed with "Cancelled after 15m". I'm not sure what happened. Anyway, I clicked on re-run failed jobs. |
Sorry, something went wrong.
|
There was a GitHub incident, thank you! |
Sorry, something went wrong.
⚠️⚠️⚠️ Buildbot failure ⚠️⚠️⚠️Hi! The buildbot x86-64 MacOS Intel ASAN NoGIL 3.x (tier-2) has failed when building commit 197607e. What do you need to do:
You can take a look at the buildbot page here: https://buildbot.python.org/#/builders/1366/builds/8195 Failed tests:
Failed subtests:
Summary of the results of the build (if available): == Click to see traceback logsTraceback (most recent call last):
File "/Users/buildbot/buildarea/3.x.itamaro-macos-intel-aws.macos-with-brew.asan.nogil/build/Lib/test/test_capi/test_mem.py", line 195, in test_buffer_overflow
self.assertIn(b'AddressSanitizer', out.err)
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: b'AddressSanitizer' not found in b'Fatal Python error: preconfig_init_allocator: PYTHONMALLOC: unknown allocator\nPython runtime state: preinitializing\n\nStack (most recent call first):\n <freed thread state>\n'
Traceback (most recent call last):
File "<string>", line 10, in <module>
File "<frozen importlib._bootstrap>", line 838, in module_from_spec
File "<frozen importlib._bootstrap_external>", line 1032, in create_module
File "<frozen importlib._bootstrap>", line 543, in _call_with_frames_removed
ImportError: module _test_module_state_shared does not support loading in subinterpreters
xpected failure
|
Sorry, something went wrong.
|
Aargh, I wrote #158932 to fix the test. |
Sorry, something went wrong.
|
@StanFromIreland: Ah, test_capi.AddressSanitizerTests.test_buffer_overflow() failed on x86-64 MacOS Intel ASAN NoGIL 3.x because PYTHONMALLOC=malloc is not supported on Free Threading. FAIL: test_buffer_overflow (test.test_capi.test_mem.AddressSanitizerTests.test_buffer_overflow) AssertionError: b'AddressSanitizer' not found in b'Fatal Python error: preconfig_init_allocator: PYTHONMALLOC: unknown allocator\nPython runtime state: preinitializing\n\nStack (most recent call first):\n <freed thread state>\n' Re-running test_capi in verbose mode (matching: test_buffer_overflow) FAIL: test_buffer_overflow (test.test_capi.test_mem.AddressSanitizerTe Problem: the buffer overflow is not detected using mimalloc: `PYTHONMALLOC=mimalloc ./python -c 'import _testcapi; _testcapi.pymem_buffer_overflow()' exits successfully. I suppose that skipping the test on Free Threading is an acceptable trade-off for now. Note: the overflow is detected using PYTHONMALLOC=mimalloc_debug (or PYTHONMALLOC=debug which means the same). $ PYTHONMALLOC=debug ./python -c 'import _testcapi; _testcapi.pymem_buffer_overflow()'
Debug memory block at address p=0x7b04fa0c0ee0: API 'm'
16 bytes originally requested
The 7 pad bytes at p-7 are FORBIDDENBYTE, as expected.
The 8 pad bytes at tail=0x7b04fa0c0ef0 are not all FORBIDDENBYTE (0xfd):
at tail+0: 0x78 *** OUCH
at tail+1: 0xfd
at tail+2: 0xfd
at tail+3: 0xfd
at tail+4: 0xfd
at tail+5: 0xfd
at tail+6: 0xfd
at tail+7: 0xfd
Data at p: cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd cd
Enable tracemalloc to get the memory block allocation traceback
Fatal Python error: _PyMem_DebugRawFree: bad trailing pad byte
Python runtime state: initialized
Stack (most recent call first):
File "<string>", line 1 in <module>
Extension modules: _testcapi (total: 1)
Aborted PYTHONMALLOC=debug ./python -c 'import _testcapi; _testcapi.pymem_buffer_overflow()'
|
Sorry, something went wrong.
However, that is CPython's own debug-hooks checker, not {HW}ASan. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
This supersedes GH-149166 and GH-156050, pulling in their changes and adding a --with-hwaddress-sanitizer configure option as well as a few little miscellaneous changes for better support. Note that x86-64 has to use clang's page aliasing
mode, which shares the heap across fork(), so the test suite is only reliable
on AArch64.
@AnnaAr321 and @fmayer I'd appreciate your reviews :-)