diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2025-06-07 18:56:38 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-06-07 18:56:38 (GMT) |
commit | ef539654e682cc451ea68fa366a16e9020df89b8 (patch) | |
tree | 4483914c306b8b878827da8811f5575a76cc6029 /Python/remote_debugging.c | |
parent | 3faf00e0031652cb067ddfce7c61574567e2742d (diff) | |
download | cpython-ef539654e682cc451ea68fa366a16e9020df89b8.zip cpython-ef539654e682cc451ea68fa366a16e9020df89b8.tar.gz cpython-ef539654e682cc451ea68fa366a16e9020df89b8.tar.bz2 |
[3.14] gh-134876: Add fallback for when process_vm_readv fails with ENOSYS (GH-134878) (#135240)
gh-134876: Add fallback for when process_vm_readv fails with ENOSYS (GH-134878)
(cherry picked from commit ac9c3431cc5916a795c42b3e2b965233ceffe6f0)
Co-authored-by: Daniel Golding <goldingd89@gmail.com>
Diffstat (limited to 'Python/remote_debugging.c')
-rw-r--r-- | Python/remote_debugging.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/Python/remote_debugging.c b/Python/remote_debugging.c index dd55b78..7aee87e 100644 --- a/Python/remote_debugging.c +++ b/Python/remote_debugging.c @@ -24,6 +24,39 @@ read_memory(proc_handle_t *handle, uint64_t remote_address, size_t len, void* ds return _Py_RemoteDebug_ReadRemoteMemory(handle, remote_address, len, dst); } +// Why is pwritev not guarded? Except on Android API level 23 (no longer +// supported), HAVE_PROCESS_VM_READV is sufficient. +#if defined(__linux__) && HAVE_PROCESS_VM_READV +static int +write_memory_fallback(proc_handle_t *handle, uintptr_t remote_address, size_t len, const void* src) +{ + if (handle->memfd == -1) { + if (open_proc_mem_fd(handle) < 0) { + return -1; + } + } + + struct iovec local[1]; + Py_ssize_t result = 0; + Py_ssize_t written = 0; + + do { + local[0].iov_base = (char*)src + result; + local[0].iov_len = len - result; + off_t offset = remote_address + result; + + written = pwritev(handle->memfd, local, 1, offset); + if (written < 0) { + PyErr_SetFromErrno(PyExc_OSError); + return -1; + } + + result += written; + } while ((size_t)written != local[0].iov_len); + return 0; +} +#endif // __linux__ + static int write_memory(proc_handle_t *handle, uintptr_t remote_address, size_t len, const void* src) { @@ -39,6 +72,9 @@ write_memory(proc_handle_t *handle, uintptr_t remote_address, size_t len, const } while (result < len); return 0; #elif defined(__linux__) && HAVE_PROCESS_VM_READV + if (handle->memfd != -1) { + return write_memory_fallback(handle, remote_address, len, src); + } struct iovec local[1]; struct iovec remote[1]; Py_ssize_t result = 0; @@ -52,6 +88,9 @@ write_memory(proc_handle_t *handle, uintptr_t remote_address, size_t len, const written = process_vm_writev(handle->pid, local, 1, remote, 1, 0); if (written < 0) { + if (errno == ENOSYS) { + return write_memory_fallback(handle, remote_address, len, src); + } PyErr_SetFromErrno(PyExc_OSError); return -1; } |