Skip to content

Off-by-one error in Lib/multiprocessing/util.py _SUN_PATH_MAX calculation causes forkserver OSError: AF_UNIX path too long #140734

Closed

Description

@zmedico

Bug report

Bug description:

This test case fails with OSError: AF_UNIX path too long on Linux if the adjustment argument is 0, and succeeds if the adjustment argument is 1:

#!/usr/bin/env python3.14

import multiprocessing
import os
import sys

from multiprocessing.util import _SUN_PATH_MAX


def target():
    print("fork was successful")


def run_proc(adjustment):
    os.environ["TMPDIR"] = (
        "/tmp/" + (_SUN_PATH_MAX - len("/tmp/") - 14 - 14 - adjustment) * "X"
    )
    os.makedirs(os.environ["TMPDIR"], exist_ok=True)
    print("TMPDIR length", len(os.environ["TMPDIR"]))
    proc = multiprocessing.Process(target=target)
    proc.start()
    try:
        proc.join()
    finally:
        try:
            os.rmdir(os.environ["TMPDIR"])
        except OSError:
            pass


def main(argv):
    adjustment = int(argv[1])
    run_proc(adjustment)


if __name__ == "__main__":
    main(sys.argv)

Test results:

$ for adjustment in 0 1; do ./forkserver_bug.py $adjustment; done
TMPDIR length 80
Traceback (most recent call last):
  File "/home/zmedico/./forkserver_bug.py", line 37, in <module>
    main(sys.argv)
    ~~~~^^^^^^^^^^
  File "/home/zmedico/./forkserver_bug.py", line 33, in main
    run_proc(adjustment)
    ~~~~~~~~^^^^^^^^^^^^
  File "/home/zmedico/./forkserver_bug.py", line 21, in run_proc
    proc.start()
    ~~~~~~~~~~^^
  File "/usr/lib/python3.14/multiprocessing/process.py", line 121, in start
    self._popen = self._Popen(self)
                  ~~~~~~~~~~~^^^^^^
  File "/usr/lib/python3.14/multiprocessing/context.py", line 224, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/lib/python3.14/multiprocessing/context.py", line 300, in _Popen
    return Popen(process_obj)
  File "/usr/lib/python3.14/multiprocessing/popen_forkserver.py", line 35, in __init__
    super().__init__(process_obj)
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/lib/python3.14/multiprocessing/popen_fork.py", line 20, in __init__
    self._launch(process_obj)
    ~~~~~~~~~~~~^^^^^^^^^^^^^
  File "/usr/lib/python3.14/multiprocessing/popen_forkserver.py", line 51, in _launch
    self.sentinel, w = forkserver.connect_to_new_process(self._fds)
                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "/usr/lib/python3.14/multiprocessing/forkserver.py", line 89, in connect_to_new_process
    self.ensure_running()
    ~~~~~~~~~~~~~~~~~~~^^
  File "/usr/lib/python3.14/multiprocessing/forkserver.py", line 157, in ensure_running
    listener.bind(address)
    ~~~~~~~~~~~~~^^^^^^^^^
OSError: AF_UNIX path too long
TMPDIR length 79
fork was successful

I think this would fix it for Linux, but I'm not sure about other platforms:

--- a/Lib/multiprocessing/util.py
+++ b/Lib/multiprocessing/util.py
@@ -176,5 +176,5 @@ def _get_base_temp_dir(tempfile):
     #   len(base_tempdir + '/pymp-XXXXXXXX' + '/sock-XXXXXXXX')
     sun_path_len = len(base_tempdir) + 14 + 14
-    if sun_path_len <= _SUN_PATH_MAX:
+    if sun_path_len < _SUN_PATH_MAX:
         return base_tempdir
     # Fallback to the default system-wide temporary directory.
@@ -202,5 +202,5 @@ def _get_base_temp_dir(tempfile):
     warn("Ignoring user-defined temporary directory: %s", base_tempdir)
     # at most max(map(len, dirlist)) + 14 + 14 = 36 characters
-    assert len(base_system_tempdir) + 14 + 14 <= _SUN_PATH_MAX
+    assert len(base_system_tempdir) + 14 + 14 < _SUN_PATH_MAX
     return base_system_tempdir

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Activity

  1. added
    stdlibStandard Library Python modules in the Lib/ directory
    on Oct 29, 2025
  2. sergey-miryanov commented on Oct 29, 2025

    @sergey-miryanov
    Contributor

    @zmedico Do you want to prepare a PR?

  3. picnixz commented on Oct 29, 2025

    @picnixz
    Member

    Thanks for catching this. Out of curiosity, was it an issue in practice?

  4. thesamesam commented on Oct 29, 2025

    @thesamesam
    Contributor
  5. picnixz commented on Oct 29, 2025

    @picnixz
    Member

    Thank you. But in your case it would still be an issue as now the restriction is even stricter, right?

  6. thesamesam commented on Oct 29, 2025

    @thesamesam
    Contributor

    I don't think so - with the fixed length, the code from #134085 will fallback correctly to another tempdir, right? It's just that it didn't account for a path that is on the boundary.

  7. picnixz commented on Oct 29, 2025

    @picnixz
    Member

    I forgot about my own fallback :') I think for BSD* systems, 104 also includes a null termination so other nix-based distros should be fine (after the fix).

  8. self-assigned this
    on Oct 29, 2025
  9. picnixz commented on Oct 29, 2025

    @picnixz
    Member

    I'm going to work on this one but won't be able to fix until this w-e (anyway, the next release is in 2 months and this isn't enough for a quick release). The patch is really easy but I want an additional test but the tests are a bit too intricate.

  10. YvesDup commented on Oct 29, 2025

    @YvesDup
    Contributor

    think this would fix it for Linux, but I'm not sure about other platforms:

    Run perfectly on MacOSX regardless of adjustment value

  11. picnixz commented on Oct 29, 2025

    @picnixz
    Member

    For macOS, _SUN_PATH_MAX should be 92 I guess as it was the most conservative estimate for POSIX systems. If the real limit is above, then it won't be an issue indeed.

  12. YvesDup commented on Oct 29, 2025

    @YvesDup
    Contributor

    For macOS, _SUN_PATH_MAX is 92.

  13. picnixz commented on Oct 29, 2025

    @picnixz
    Member

    Yes, but the real bound may be different. I couldn't find documentation telling me what the exact value is so I took the most conservative one. If your kernel implementation uses another value (maybe 108), then you won't see the crash.

    If you want to check your runtime _SUN_PATH_MAX, try to change that limit until when the reproducer fails.

  14. picnixz commented on Nov 2, 2025

    @picnixz
    Member

    I gave up on testing this. It's too annoying and the tests wouldn't really be that interesting. Anyone can add testing in a follow-up PR though.

  15. added a commit that references this issue on Nov 7, 2025
  16. added 2 commits that reference this issue on Nov 7, 2025
  17. added 2 commits that reference this issue on Nov 7, 2025
  18. picnixz commented on Nov 7, 2025

    @picnixz
    Member

    Thanks for the report!

  19. thesamesam commented on Nov 7, 2025

    @thesamesam
    Contributor

    Thank you!

  20. added a commit that references this issue on Dec 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

3.13only security fixes3.14bugs and security fixes3.15bugs and security fixesOS-linuxstdlibStandard Library Python modules in the Lib/ directorytopic-multiprocessingtype-bugAn unexpected behavior, bug, or error

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions