summaryrefslogtreecommitdiffstats
path: root/Python/remote_debugging.c
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2025-06-07 18:56:38 (GMT)
committerGitHub <noreply@github.com>2025-06-07 18:56:38 (GMT)
commitef539654e682cc451ea68fa366a16e9020df89b8 (patch)
tree4483914c306b8b878827da8811f5575a76cc6029 /Python/remote_debugging.c
parent3faf00e0031652cb067ddfce7c61574567e2742d (diff)
downloadcpython-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.c39
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;
}