Skip to content

importlib: PermissionError during startup if working directory isn't readable #115911

@moreati

Description

@moreati

Bug report

Bug description:

On macOS importlib._bootstrap_external.PathFinder._path_importer_cache() raises PermissionError during interpreter startup if '' is included in sys.path and the current working directory is not readable.

Reproduction

Given a CWD that is not readable by fred, the user fred cannot run Python

➜  private su fred -c "whoami; python3.13 -c 'pass'"
Password:
fred
Traceback (most recent call last):
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1322, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1262, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1544, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1516, in _get_spec
  File "<frozen importlib._bootstrap_external>", line 1495, in _path_importer_cache
PermissionError: [Errno 13] Permission denied

➜  private uname -mv; whoami; pwd; ls -ld                                                        
Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:44 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T6000 arm64
alex
/Users/alex/private
drwx------  2 alex  staff  64 25 Feb 10:44 .

➜  private python3.13 -c "import sys;print(sys.version)"           
3.13.0a4+ (heads/main:6550b54813, Feb 25 2024, 10:56:11) [Clang 15.0.0 (clang-1500.1.0.2.5)]

Workaround

Adding -P, prevents '' being added to sys.path, so avoids the exception

➜  private su fred -c "whoami; python3.13 -P -c 'pass'"                                    
Password:
fred

Discussion

On macOS the libc function getcwd() can return EACCES. From the manpage

[EACCES] Read or search permission was denied for a component of the pathname. This is only checked in limited cases, depending on implementation details.

When searching for importable modules PathFinder._path_importer_cache() attempts to determine the cwd by calling os.getcwd(), it handles a FileNotFoundError exception, but not PermissionError. Because PathFinder is used during interpreter startup user code has no opportunity to catch the exception.

Proposed fix

Ignore PermissionError in PathFinder._path_importer_cache(), the same way FileNotFoundError is currently. This would result in imports succeeding, but without getting cached. E.g. applying the below change & rebuilding/reinstalling

➜  private su fred -c "whoami; python3.13 -c 'import sys;print(sys.version)'"
Password:
fred
3.13.0a4+ (heads/main:6550b54813, Feb 25 2024, 10:56:11) [Clang 15.0.0 (clang-1500.1.0.2.5)]

I'm happy to submit a PR with this, and unit tests as deemed suitable

➜  cpython git:(main) ✗ git diff
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 2a9aef0317..5d1f4f1de0 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -1493,7 +1493,7 @@ def _path_importer_cache(cls, path):
         if path == '':
             try:
                 path = _os.getcwd()
-            except FileNotFoundError:
+            except (FileNotFoundError, PermissionError):
                 # Don't cache the failure as the cwd can easily change to
                 # a valid directory later on.
                 return None

Other Python Versions

In Python 3.10, 3.11 & 3.12 the same exception can occur when user code imports a non-builtin module (e.g. base64, zlib), but it does not occur during interpreter startup. I presume this is due to a change in which modules are required during interpreter initialisation.

➜  private su fred -c "whoami; python3.10 -c 'import sys;print(sys.version);import zlib'"              
Password:
fred
3.10.13 (main, Aug 24 2023, 12:59:26) [Clang 15.0.0 (clang-1500.1.0.2.5)]
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1002, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 945, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1439, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1408, in _get_spec
  File "<frozen importlib._bootstrap_external>", line 1366, in _path_importer_cache
PermissionError: [Errno 13] Permission denied

➜  private su fred -c "whoami; python3.11 -c 'import sys;print(sys.version);import zlib'"
Password:
fred
3.11.7 (main, Dec  4 2023, 18:10:11) [Clang 15.0.0 (clang-1500.1.0.2.5)]
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1138, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1078, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1504, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1473, in _get_spec
  File "<frozen importlib._bootstrap_external>", line 1431, in _path_importer_cache
PermissionError: [Errno 13] Permission denied

➜  private su fred -c "whoami; python3.12 -c 'import sys;print(sys.version);import zlib'"
Password:
fred
3.12.1 (main, Dec  7 2023, 20:45:44) [Clang 15.0.0 (clang-1500.1.0.2.5)]
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "<frozen importlib._bootstrap>", line 1360, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1322, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 1262, in _find_spec
  File "<frozen importlib._bootstrap_external>", line 1524, in find_spec
  File "<frozen importlib._bootstrap_external>", line 1496, in _get_spec
  File "<frozen importlib._bootstrap_external>", line 1475, in _path_importer_cache
PermissionError: [Errno 13] Permission denied

CPython versions tested on:

3.10, 3.11, 3.12, CPython main branch

Operating systems tested on:

macOS

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibPython modules in the Lib dirtopic-importlibtype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy