Skip to content

Server does not validate socket path length; overrun surfaces as a raw tmux File name too long #725

Description

@tony

Filed against tmux-python/libtmux v0.62.0. Found while writing tested documentation examples that place sockets under a temporary directory.

What happens

Server(socket_path=...) accepts any path. UNIX domain socket paths are capped by sun_path in struct sockaddr_un — 108 bytes on Linux, 104 on macOS — so a path longer than that cannot work, but nothing says so until the first tmux command runs and fails with a raw tmux error.

        if socket_path is not None:
            self.socket_path = socket_path

The path that fails is usually not one the caller typed. It is tmp_path from a pytest fixture, an XDG runtime dir, a nested worktree, or a CI checkout under a long workspace prefix — so the number the user needs (how many bytes over) is exactly the number the error does not give them.

Recreation

import os, pathlib, tempfile
root = pathlib.Path(tempfile.mkdtemp(prefix="repro-"))
deep = root.joinpath(*["d" * 40] * 4) / "sock"
deep.parent.mkdir(parents=True, exist_ok=True)
print("path length:", len(str(deep)), "(UNIX socket limit is ~107)")
from libtmux.server import Server

server = Server(socket_path=str(deep))
print("constructed fine; socket_path =", server.socket_path)
try:
    server.new_session(session_name="demo")
except Exception as exc:
    print(f"{type(exc).__module__}.{type(exc).__name__}: {exc}")

Observed on libtmux v0.62.0 / tmux 3.7b:

path length: 188 (UNIX socket limit is ~107)
constructed fine; socket_path = /tmp/repro-.../dddd.../sock
libtmux.exc.LibTmuxException: new-session: error connecting to /tmp/repro-.../sock (File name too long)

Two problems in that outcome. The construction that was already doomed succeeded, and the diagnosis arrives as a passed-through File name too long from tmux at some arbitrary later call — attributed to new-session, which is not what is wrong.

Prior art in this repo

The constraint is already known internally. libtmux.pytest_plugin avoids deep tmp_path sockets, and the engine-ops line uses tempfile.mkdtemp() rather than tmp_path for exactly this reason. It is knowledge held in comments rather than in the API.

What a fix needs

  1. Validate in Server.__init__ when socket_path is given: if len(os.fsencode(path)) > 107 (or a platform-derived limit), raise a dedicated exception naming the length, the limit, and the path. A new libtmux.exc.SocketPathTooLong(LibTmuxException) fits the existing exception tree in src/libtmux/exc.py.
  2. Do the same for socket_name, which resolves to <socket_dir>/tmux-<euid>/<name> and can overrun via a long $TMUX_TMPDIR even with a short name. This is the case that actually bites people, since the long part is inherited from the environment rather than passed in.
  3. Add the limit and the workaround (tempfile.mkdtemp(), or a short TMUX_TMPDIR) to the Server docstring and to the pytest-plugin documentation, where users hitting it via tmp_path will look.

Validation at construction is worth more than a better error at call time: the object is the thing that is wrong, and it is cheap to say so while the caller still has the stack frame that built it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions