New submission from Christophe Zeitouny:

Looks like faulthandler is not properly tearing down its sigaltstack, causing 
potential double-free issues in any application that embeds the Python 
interpreter.
I stumbled upon this when I enabled AddressSanitizer on my application, which 
sets up and tears down a Python interpreter instance at runtime. 
AddressSanitizer complained about a double-free of the stack_t::ss_sp memory 
region.
After close inspection, here's what's happening:

1. When a new thread is created, AddressSanitizer sets up its own alternative 
stack by calling sigaltstack
2. Py_Initialize() is called, which initializes faulthandler, which sets up its 
own alternative stack, therefore overriding the one installed by 
AddressSanitizer
3. Py_Finalize() is called, which deinitializes faulthandler, which merely 
deletes the allocated stack region, but leaves the alternative stack installed. 
Any signal that occurs after this point will be using a memory region it 
doesn't own as stack. dangerous stuff.
4. The thread exits, at which point AddressSanitizer queries sigaltstack for 
the current alternative stack, blindly assumes that it's the same one that it 
installed, and attempts to free the allocated stack region. Therefore causing a 
double free issue

Regardless of the fact that AddressSanitizer should probably not blindly trust 
that the currently installed sigaltstack is the same one it installed earlier, 
the current code in faulthandler leaves the sigaltstack in a very bad state 
after finalizing.
This means that the application that embeds the Python interpreter better hope 
that no signals are raised after it calls Py_Finalize().

I have a patch that fixes this issue. faulthandler will save the previously 
installed alternative stack at initialization time. During deinitialization, it 
will query sigaltstack for the current stack. If it's the same as the one it 
installed,
it will restore the saved previous stack.

'sigaltstack' just sounds like a badly designed API. There is essentially no 
way to use it 'correctly'.
Here's how AddressSanitizer uses it (line 164): 
http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc?view=markup
and here's how the Chrome browser uses it: 
https://chromium.googlesource.com/breakpad/breakpad/+/chrome_43/src/client/linux/handler/exception_handler.cc#149

Notice that my approach is closer to what Chrome does, but in the case where 
the installed stack is no longer ours, I don't disable whatever stack is 
installed. This is because I don't believe that will make much difference. 
Whoever switched out the stack could have
saved our stack somewhere and planned on blindly restoring it upon exit. In 
which case, whatever we do would be overridden.

Attached are a tiny reproducer for the issue, along with the complete analysis 
of what's reported by AddressSanitizer. I'll follow this up by a pull request 
for my changes.

Thanks!
Chris

----------
components: Extension Modules
files: python_failure.txt
messages: 290025
nosy: haypo, tich
priority: normal
severity: normal
status: open
title: faulthandler does not properly restore sigaltstack during teardown
type: enhancement
Added file: http://bugs.python.org/file46754/python_failure.txt

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue29884>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to