#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h> /* for process_vm_readv */
+#ifndef HAVE_PROCESS_VM
+#include <dlfcn.h>
+#endif /* !HAVE_PROCESS_VM */
#endif /* HAVE_SYS_UIO_H */
#ifndef SYS_SECCOMP
/* Number of tracees children are allowed to create. */
#define MAX_TRACEES 4096
-#ifdef HAVE_SECCOMP
+#if defined HAVE_SYS_UIO_H && !defined HAVE_PROCESS_VM
-/* Whether to enable seccomp acceleration. */
-static bool use_seccomp_p;
+/* Load have_process_vm dynamically if possible to avoid PTRACE_PEEKDATA
+ restrictions on Android 15 QPR2+. */
-#else /* !HAVE_SECCOMP */
-#define use_seccomp_p (false)
-#endif /* HAVE_SECCOMP */
+static ssize_t (*process_vm_readv) (pid_t, const struct iovec *,
+ unsigned long,
+ const struct iovec *,
+ unsigned long, unsigned long);
+static ssize_t (*process_vm_writev) (pid_t, const struct iovec *,
+ unsigned long,
+ const struct iovec *,
+ unsigned long, unsigned long);
+
+#endif /* HAVE_SYS_UIO_H && !HAVE_PROCESS_VM */
#ifdef __aarch64__
ADDRESS. Return its contents in BUFFER.
If there are unreadable pages within ADDRESS + N, the contents of
- BUFFER after the first such page becomes undefined. */
+ BUFFER after the first such page become undefined. */
static void
read_memory (struct exec_tracee *tracee, char *buffer,
{
USER_WORD word, n_words, n_bytes, i;
long rc;
-#ifdef HAVE_PROCESS_VM
+#ifdef HAVE_SYS_UIO_H
struct iovec iov, remote;
/* If `process_vm_readv' is available, use it instead. */
read, consider the read to have been a success. */
if (n <= SSIZE_MAX
- && ((size_t) process_vm_readv (tracee->pid, &iov, 1,
- &remote, 1, 0) != -1))
+#ifndef HAVE_PROCESS_VM
+ && process_vm_readv
+#endif /* !HAVE_PROCESS_VM */
+ && (process_vm_readv (tracee->pid, &iov, 1,
+ &remote, 1, 0) != -1))
return;
-#endif /* HAVE_PROCESS_VM */
+#endif /* !HAVE_SYS_UIO_H */
/* First, read entire words from the tracee. */
n_words = n & ~(sizeof (USER_WORD) - 1);
{
USER_WORD start, end, word;
unsigned char *bytes;
-#ifdef HAVE_PROCESS_VM
+#ifdef HAVE_SYS_UIO_H
struct iovec iov, remote;
/* Try to use `process_vm_writev' if possible, but fall back to
remote.iov_len = n;
if (n <= SSIZE_MAX
- && ((size_t) process_vm_writev (tracee->pid, &iov, 1,
- &remote, 1, 0) == n))
+#ifndef HAVE_PROCESS_VM
+ && process_vm_writev
+#endif /* !HAVE_PROCESS_VM */
+ && (process_vm_writev (tracee->pid, &iov, 1,
+ &remote, 1, 0) == n))
return 0;
-#endif /* HAVE_PROCESS_VM */
+#endif /* HAVE_SYS_UIO_H */
/* Calculate the start and end positions for the write. */
return 0;
/* Now check if the caller is looking for /proc/self/exe or its
- equivalent with the PID made explicit.
-
- dirfd can be ignored, as for now only absolute file names are
- handled. FIXME. */
+ equivalent with the PID made explicit. */
p = stpcpy (proc_pid_exe, "/proc/");
p = format_pid (p, tracee->pid);
if (!address
|| user_copy (tracee, (unsigned char *) tracee->exec_file,
- address, length))
+ address, length + 1))
goto fail;
/* Replace the file name buffer with ADDRESS. */
#endif /* HAVE_SECCOMP */
loader_name = loader;
-#ifdef HAVE_SECCOMP
- errno = 0;
- prctl (PR_GET_SECCOMP);
-
- /* PR_GET_SECCOMP should not set errno if the kernel was configured
- with support for seccomp. */
- if (!errno)
- use_seccomp_p = true;
- else
- return;
-
- /* Establish whether the kernel is 4.7.x or older. */
- uname (&u);
- if ((sscanf (u.release, "%d.%d", &major, &minor) == 2))
- {
- /* Certain required ptrace features were introduced in kernel
- 3.5. */
- if (major < 3 || (major == 3 && minor < 5))
- use_seccomp_p = false;
- else
- {
- if (major < 4 || (major == 4 && minor <= 7))
- kernel_4_7_or_earlier = true;
- }
- }
-#endif /* HAVE_SECCOMP */
+#if defined HAVE_SYS_UIO_H && !defined HAVE_PROCESS_VM
+ {
+ *(void **) (&process_vm_readv)
+ = dlsym (RTLD_DEFAULT, "process_vm_readv");
+ *(void **) (&process_vm_writev)
+ = dlsym (RTLD_DEFAULT, "process_vm_writev");
+ }
+#endif /* HAVE_SYS_UIO_H && !HAVE_PROCESS_VM */
}