When process_vm_readv fails with EPERM, try PTRACE_PEEKDATA

process_vm_readv() and ptrace(PTRACE_PEEKDATA) have inconsistent access
control rules wrt traced processes: process_vm_readv() is more likely to
fail with EPERM than ptrace(PTRACE_PEEKDATA) when tracing a process that
has execve'd a privileged executable.

* util.c (umoven, umovestr): If process_vm_readv returned EPERM,
fall back to ptrace(PTRACE_PEEKDATA).

Reported-by: Andrew Guertin <lists@dolphinling.net>
diff --git a/util.c b/util.c
index fd9053a..1bec3c2 100644
--- a/util.c
+++ b/util.c
@@ -1003,10 +1003,13 @@
 			case ENOSYS:
 				process_vm_readv_not_supported = 1;
 				break;
+			case EPERM:
+				/* operation not permitted, try PTRACE_PEEKDATA */
+				break;
 			case ESRCH:
 				/* the process is gone */
 				return -1;
-			case EFAULT: case EIO: case EPERM:
+			case EFAULT: case EIO:
 				/* address space is inaccessible */
 				return -1;
 			default:
@@ -1158,7 +1161,12 @@
 				case ESRCH:
 					/* the process is gone */
 					return -1;
-				case EFAULT: case EIO: case EPERM:
+				case EPERM:
+					/* operation not permitted, try PTRACE_PEEKDATA */
+					if (!nread)
+						goto vm_readv_didnt_work;
+					/* fall through */
+				case EFAULT: case EIO:
 					/* address space is inaccessible */
 					if (nread) {
 						perror_msg("umovestr: short read (%d < %d) @0x%lx",