[issue36646] os.listdir() got permission error in Python3.6 but it's fine in Python2.7

Eryk Sun report at bugs.python.org
Thu Apr 18 09:17:19 EDT 2019


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

For me in Windows 10, os.listdir(u"C:\\Temp") uses the same sequence of WINAPI and NT system calls in 2.7 and 3.6.

Setup the query for all files ("*"), and return the first matching entry:

    FindFirstFileW
        FindFirstFileExW

            NtOpenFile(
                ObjectAttributes=(
                    ObjectName="\??\C:\Temp\",
                    Attributes=OBJ_CASE_INSENSITIVE)
                DesiredAccess=(
                    SYNCHRONIZE | 
                    FILE_LIST_DIRECTORY),
                ShareAccess=(
                    FILE_SHARE_READ | 
                    FILE_SHARE_WRITE | 
                    FILE_SHARE_DELETE),
                OpenOptions=(
                    FILE_DIRECTORY_FILE | 
                    FILE_SYNCHRONOUS_IO_NONALERT |
                    FILE_OPEN_FOR_BACKUP_INTENT))

            NtQuerDirectoryFileEx(
                FileInformationClass=FileBothDirectoryInformation, 
                QueryFlags=SL_RETURN_SINGLE_ENTRY,
                FileName="*")

Repeat for the remaining entries:

    FindNextFileW

        Return the next entry from a 4 KiB buffer. If the buffer is
        empty, refill it with the following call, until the query is
        exhausted (i.e. STATUS_NO_MORE_FILES):

            NtQuerDirectoryFileEx(
                FileInformationClass=FileBothDirectoryInformation,
                Length=4096)

Unfortunately, many NT status codes map to ERROR_ACCESS_DENIED (5). If it's STATUS_ACCESS_DENIED (0xC0000022), then probably NtOpenFile failed. Try checking the last NT status value with ctypes. For example:

    >>> import os, ctypes
    >>> ntdll = ctypes.WinDLL('ntdll')
    >>> ntdll.RtlGetLastNtStatus.restype = ctypes.c_ulong
    >>> try:
    ...     os.listdir(u'C:\\Users\\Administrator')
    ... except:
    ...     print(hex(ntdll.RtlGetLastNtStatus()))
    ...
    0xc0000022

Do you have any anti-malware programs running? If so, try disabling them. They can hook APIs or attach to the I/O stack with a filter driver (e.g. to deny an I/O request that's disallowed by a rule). If disabling your anti-malware software allows access, then you'll need to set a rule to grant access to Python 3.

----------

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


More information about the Python-bugs-list mailing list