Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

sys.remote_exec() is unable to find writable memory when libpython got deleted/replaced on disk #151029

Copy link
Copy link
@ambv

Description

@ambv
Issue body actions

Bug report

Bug description:

The current happy path

sys.remote_exec() looks at a remote PID's /proc/<pid>/maps, which allows it to find libpython on disk. Reading the libpython shared library file allows sys.remote_exec() to find the .PyRuntime section, which includes the debug offsets that point at the remote_debugger_support.debugger_script_path[] location where the debugger script path can be written to. The remote interpreter then finds the remotely injected update and does its thing to execute it.

The failure mode

In the case where /proc/<pid>/maps points at a libpython that got deleted from disk or replaced with a new file, this process fails early. CPython normally does not make any guarantees for such a case, but in this particular scenario we should be able to recover.

Why this is important to fix

On Linux in particular, in server environments scheduled package updates will include Python interpreter updates. When this happens, a long-running server process is now undebuggable. sys.remote_exec() is supposed to handle this very situation: allowing to debug a process without the need to kill it first.

The compatibility area between the sys.remote_exec() debugger and the debugged remote process is minimal: as long as both are the same minor version of Python (i.e. 3.14.x ←→ 3.14.x), the debug offsets structure will be parseable on both ends. ABI compatibility guarantees that no breaking changes for this use case will occur between bugfix releases within a minor release.

Suggested fix scope

Since this is mostly important for centrally managed server scenarios, I suggest we address Linux first here and decide on other platforms after this succeeds.

As for the approach: even in the case of /proc/<pid>/maps pointing at a deleted file, it is also listing the memory location where that file was loaded. We can read the same information from memory then. Of course, file segments/sections are gone at this point, so it's a bit more of an involved process. But this will be a path taken only in the case when the file no longer exists on disk.

An alternative approach could be to try to dig out the inode of the now-deleted file and read the unlinked file that way. But this requires superuser privileges, so it's out of scope for sys.remote_exec().

How to test this

Using LD_LIBRARY_PATH=, we can run a Python interpreter in such a way that it will pick up libpython from a copy in a temporary directory. Then the test will delete that copy, recreating our failure mode.

What about statically built Python?

This solution should also work for static builds. Instead of looking at libpython, we'd be looking at a deleted executable.

CPython versions tested on:

3.14

Operating systems tested on:

Linux

Linked PRs

Reactions are currently unavailable

Metadata

Metadata

Assignees

Labels

interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    Morty Proxy This is a proxified and sanitized view of the page, visit original site.