[issue46888] SharedMemory.close() destroys memory

Eryk Sun report at bugs.python.org
Wed Mar 2 06:33:21 EST 2022


Eryk Sun <eryksun at gmail.com> added the comment:

Putting words into action, here's an example of what a privileged process (e.g. running as SYSTEM) can do if a script or application is written to call the undocumented NT API function NtMakePermanentObject(). A use case would be a script running as a system service that needs a shared-memory section object to persist after the service is stopped or terminated, e.g. such that the section is still accessible if the service is resumed. Anyway, this is just an example of what's possible, from a technical perspective. Also, note that I granted SeCreatePermanentPrivilege to my current user for this example, so it's certainly not required to use the SYSTEM account. An administrator can grant this privilege to any account.

By default, named kernel objects are temporary:

    >>> import os, _winapi, ctypes
    >>> from multiprocessing.shared_memory import SharedMemory
    >>> name = f'spam_{os.getpid()}'
    >>> m = SharedMemory(name, True, 8192)
    >>> m.close()
    >>> try: SharedMemory(name)
    ... except OSError as e: print(e)
    ...
    [WinError 2] The system cannot find the file specified: 'spam_6592'

Global permanent example:

Enable privileges for the current thread:

    >>> import win32api; from win32security import *
    >>> ImpersonateSelf(SecurityImpersonation)
    >>> da = TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES
    >>> ht = OpenThreadToken(win32api.GetCurrentThread(), da, False)
    >>> ps = [[0, SE_PRIVILEGE_ENABLED], [0, SE_PRIVILEGE_ENABLED]]
    >>> ps[0][0] = LookupPrivilegeValue(None, 'SeCreatePermanentPrivilege')
    >>> ps[1][0] = LookupPrivilegeValue(None, 'SeCreateGlobalPrivilege')
    >>> AdjustTokenPrivileges(ht, False, ps)
    ((16, 0),)

Create a global section object, and make it permanent:

    >>> name = rf'Global\spam_{os.getpid()}'
    >>> m = SharedMemory(name, True, 8192)
    >>> from win32con import DELETE
    >>> h = _winapi.OpenFileMapping(DELETE, False, name)
    >>> ntdll = ctypes.WinDLL('ntdll')
    >>> ntdll.NtMakePermanentObject(h)
    0
    >>> _winapi.CloseHandle(h)

A permanent object persists after the last handle is closed:

    >>> m.close()
    >>> m = SharedMemory(name) # This works now.

Make the section object temporary again:

    >>> h = _winapi.OpenFileMapping(DELETE, False, name)
    >>> ntdll.NtMakeTemporaryObject(h)
    0
    >>> _winapi.CloseHandle(h)
    >>> m.close()
    >>> try: SharedMemory(name)
    ... except OSError as e: print(e)
    ...
    [WinError 2] The system cannot find the file specified: 'Global\\spam_6592'

----------

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue46888>
_______________________________________


More information about the Python-bugs-list mailing list