1 |
commit: 9a927b63d0f76fb5edaf4abf43784419b944f21c |
2 |
Author: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Sep 20 22:10:01 2015 +0000 |
4 |
Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Sep 20 22:10:01 2015 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=9a927b63 |
7 |
|
8 |
libsandbox: fix process_vm_readv addresses/lengths |
9 |
|
10 |
The current logic calculates the lengths/base addresses incorrectly |
11 |
leading to some kernels/mappings to reject accesses. Make sure we |
12 |
calculate the initial length properly, and then increment the base |
13 |
by that value later on. |
14 |
|
15 |
With those fixes in place, we can clean up the warning/exit paths. |
16 |
|
17 |
URL: https://bugs.gentoo.org/560396 |
18 |
Reported-by: Jeroen Roovers <jer <AT> gentoo.org> |
19 |
Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org> |
20 |
|
21 |
libsandbox/trace.c | 28 ++++++++++++++-------------- |
22 |
1 file changed, 14 insertions(+), 14 deletions(-) |
23 |
|
24 |
diff --git a/libsandbox/trace.c b/libsandbox/trace.c |
25 |
index 47d2bdf..99ef8cd 100644 |
26 |
--- a/libsandbox/trace.c |
27 |
+++ b/libsandbox/trace.c |
28 |
@@ -93,10 +93,14 @@ static char *do_peekstr(unsigned long lptr) |
29 |
#ifdef HAVE_PROCESS_VM_READV |
30 |
struct iovec liov, riov; |
31 |
|
32 |
- /* We can't cross remote page boundaries when using this :( */ |
33 |
+ /* We can't cross remote page boundaries when using this :(. |
34 |
+ * The first call reads up to the edge of the page boundary since we |
35 |
+ * have no (easy) way of knowing if the next page is valid. This is |
36 |
+ * less effort than reading in the /proc/.../maps file and walking it. |
37 |
+ */ |
38 |
l = 0x1000; |
39 |
riov.iov_base = (void *)lptr; |
40 |
- len = lptr % l; |
41 |
+ len = l - (lptr % l); |
42 |
if (!len) |
43 |
len = l; |
44 |
liov.iov_base = ret = xmalloc(len); |
45 |
@@ -105,27 +109,23 @@ static char *do_peekstr(unsigned long lptr) |
46 |
while (1) { |
47 |
if (process_vm_readv(trace_pid, &liov, 1, &riov, 1, 0) == -1) { |
48 |
int e = errno; |
49 |
- if (e == ENOSYS) |
50 |
+ if (e == ENOSYS) { |
51 |
+ /* This can happen if run on older kernels but built with newer ones. */ |
52 |
+ break; |
53 |
+ } else if (e == EFAULT) { |
54 |
+ /* This can happen if the target process uses a bad pointer. #560396 */ |
55 |
break; |
56 |
- sb_eqawarn("process_vm_readv(%i, %p{%p, %zu}, 1, %p{%p, %zu}, 1, 0) failed: %s\n", |
57 |
+ } |
58 |
+ sb_ebort("ISE:do_peekstr:process_vm_readv(%i, %p{%p, %#zx}, 1, %p{%p, %#zx}, 1, 0) failed: %s\n", |
59 |
trace_pid, |
60 |
&liov, liov.iov_base, liov.iov_len, |
61 |
&riov, riov.iov_base, riov.iov_len, |
62 |
strerror(e)); |
63 |
- if (e == EFAULT) { |
64 |
- /* This sometimes happens, but it's not clear why. |
65 |
- * Throw some extended debugging info before falling |
66 |
- * back to the ptrace code. #560396 |
67 |
- */ |
68 |
- break; |
69 |
- } |
70 |
- sb_ebort("ISE:do_peekstr: process_vm_readv() hates us: %s\n", |
71 |
- strerror(e)); |
72 |
} |
73 |
|
74 |
if (memchr(liov.iov_base, '\0', liov.iov_len) != NULL) |
75 |
return ret; |
76 |
- riov.iov_base += l; |
77 |
+ riov.iov_base += riov.iov_len; |
78 |
riov.iov_len = liov.iov_len = l; |
79 |
len += l; |
80 |
ret = xrealloc(ret, len); |