Gentoo Archives: gentoo-commits

From: Mike Frysinger <vapier@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/sandbox:master commit in: libsandbox/, tests/, /
Date: Sun, 27 Sep 2015 06:13:32
Message-Id: 1442787933.0a9188fd0a812cb864819d37a6a7217a135b85f0.vapier@gentoo
1 commit: 0a9188fd0a812cb864819d37a6a7217a135b85f0
2 Author: Mike Frysinger <vapier <AT> gentoo <DOT> org>
3 AuthorDate: Sun Sep 20 22:25:33 2015 +0000
4 Commit: Mike Frysinger <vapier <AT> gentoo <DOT> org>
5 CommitDate: Sun Sep 20 22:25:33 2015 +0000
6 URL: https://gitweb.gentoo.org/proj/sandbox.git/commit/?id=0a9188fd
7
8 libsandbox: do not abort when the target uses bad pointers
9
10 If the target passes a bad pointer to the kernel, then trying to extract
11 the data via ptrace will also throw an error. The tracing code should not
12 abort though as there's no valid address to check, and kernel itself will
13 return an error for us. Simply return and move on.
14
15 URL: https://bugs.gentoo.org/560396
16 Reported-by: Jeroen Roovers <jer <AT> gentoo.org>
17 Signed-off-by: Mike Frysinger <vapier <AT> gentoo.org>
18
19 libsandbox/trace.c | 14 ++++++++++
20 localdecls.h | 4 +++
21 tests/Makefile.am | 3 +-
22 tests/script-13.sh | 5 ++++
23 tests/script.at | 1 +
24 tests/tests.h | 4 +++
25 tests/trace-memory_static_tst.c | 62 +++++++++++++++++++++++++++++++++++++++++
26 7 files changed, 92 insertions(+), 1 deletion(-)
27
28 diff --git a/libsandbox/trace.c b/libsandbox/trace.c
29 index 99ef8cd..f9194fe 100644
30 --- a/libsandbox/trace.c
31 +++ b/libsandbox/trace.c
32 @@ -59,6 +59,11 @@ static long _do_ptrace(enum __ptrace_request request, const char *srequest, void
33 }
34 sched_yield();
35 goto try_again;
36 + } else if (errno == EIO || errno == EFAULT) {
37 + /* This comes up when the child itself tries to use a bad pointer.
38 + * That's not something the sandbox should abort on. #560396
39 + */
40 + return ret;
41 } else if (!errno)
42 if (request == PTRACE_PEEKDATA ||
43 request == PTRACE_PEEKTEXT ||
44 @@ -140,7 +145,16 @@ static char *do_peekstr(unsigned long lptr)
45 while (1) {
46 a = lptr & (sizeof(long) - 1);
47 lptr -= a;
48 + errno = 0;
49 s.val = do_peekdata(lptr);
50 + if (unlikely(errno)) {
51 + if (errno == EIO || errno == EFAULT) {
52 + ret[0] = '\0';
53 + return ret;
54 + }
55 + sb_ebort("ISE:do_peekstr:do_peekdata(%#lx) failed: %s\n",
56 + lptr, strerror(errno));
57 + }
58 for (i = a; i < sizeof(long); ++i) {
59 ret[l++] = s.x[i];
60 if (!s.x[i])
61
62 diff --git a/localdecls.h b/localdecls.h
63 index 0e11fea..ecc5856 100644
64 --- a/localdecls.h
65 +++ b/localdecls.h
66 @@ -102,6 +102,10 @@ typedef struct user_regs_struct trace_regs;
67 #ifndef offsetof
68 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
69 #endif
70 +#define ALIGN_DOWN(base, size) ((base) & -(size))
71 +#define ALIGN_UP(base, size) ALIGN_DOWN((base) + (size) - 1, (size))
72 +#define PTR_ALIGN_DOWN(base, size) ((__typeof__(base))ALIGN_DOWN((uintptr_t)(base), (size)))
73 +#define PTR_ALIGN_UP(base, size) ((__typeof__(base))ALIGN_UP((uintptr_t)(base), (size)))
74
75 /* If the system is old and does not support *at funcs, then define
76 * it ourself. Shouldn't matter based on how we use it.
77
78 diff --git a/tests/Makefile.am b/tests/Makefile.am
79 index 0f0c249..3627344 100644
80 --- a/tests/Makefile.am
81 +++ b/tests/Makefile.am
82 @@ -76,7 +76,8 @@ check_PROGRAMS = \
83 pipe-fork_static_tst \
84 sb_printf_tst \
85 sigsuspend-zsh_tst \
86 - sigsuspend-zsh_static_tst
87 + sigsuspend-zsh_static_tst \
88 + trace-memory_static_tst
89
90 dist_check_SCRIPTS = \
91 $(wildcard $(srcdir)/*-[0-9]*.sh) \
92
93 diff --git a/tests/script-13.sh b/tests/script-13.sh
94 new file mode 100755
95 index 0000000..24a0e3b
96 --- /dev/null
97 +++ b/tests/script-13.sh
98 @@ -0,0 +1,5 @@
99 +#!/bin/sh
100 +# make sure poking remote addresses works even when they're bad/unaligned #560396
101 +[ "${at_xfail}" = "yes" ] && exit 77 # see script-0
102 +
103 +trace-memory_static_tst
104
105 diff --git a/tests/script.at b/tests/script.at
106 index f07a8f1..58a5077 100644
107 --- a/tests/script.at
108 +++ b/tests/script.at
109 @@ -10,3 +10,4 @@ SB_CHECK(9, [wait errpipe... done OK!])
110 SB_CHECK(10)
111 SB_CHECK(11)
112 SB_CHECK(12)
113 +SB_CHECK(13)
114
115 diff --git a/tests/tests.h b/tests/tests.h
116 index 72c678c..51dc68a 100644
117 --- a/tests/tests.h
118 +++ b/tests/tests.h
119 @@ -1,5 +1,9 @@
120 #include "headers.h"
121
122 +/* Make sure assert() works in tests. */
123 +#undef NDEBUG
124 +#include <assert.h>
125 +
126 #define _msg(std, fmt, args...) fprintf(std, "%s:%s():%i: " fmt "\n", __FILE__, __func__, __LINE__, ##args)
127 #define _stderr_msg(fmt, args...) _msg(stderr, fmt, ##args)
128 #define _stderr_pmsg(fmt, args...) _msg(stderr, fmt ": %s", ##args, strerror(errno))
129
130 diff --git a/tests/trace-memory_static_tst.c b/tests/trace-memory_static_tst.c
131 new file mode 100644
132 index 0000000..14c6477
133 --- /dev/null
134 +++ b/tests/trace-memory_static_tst.c
135 @@ -0,0 +1,62 @@
136 +/*
137 + * Make sure the process_vm_readv func can work with strings with different
138 + * alignments and lengths.
139 + *
140 + * https://bugs.gentoo.org/560396
141 + */
142 +
143 +/* We want to make some bad calls. */
144 +#undef _FORTIFY_SOURCES
145 +
146 +#include "tests.h"
147 +
148 +/* Make sure the buffer spans multiple pages. */
149 +#define SIZE 0x1000
150 +/* Make sure the buffer has plenty of slack space before/after. */
151 +static char buf[SIZE * 8];
152 +
153 +/* The smaller the span, the # of calls goes up: O(N*N*2+N). */
154 +#define COUNT 0x20
155 +#define STRIDE (SIZE / COUNT)
156 +
157 +/* Some hacks to defeat gcc warnings so we can use bad pointers. */
158 +volatile uintptr_t offset = 0;
159 +#define non_const_ptr(ptr) ((void *)((uintptr_t)(ptr) + offset))
160 +
161 +#define check_ptr(addr) \
162 +({ \
163 + printf(" open(%p)\n", addr); \
164 + ret = open(non_const_ptr(addr), O_RDONLY); \
165 + assert(ret == -1 && errno == EFAULT); \
166 +})
167 +
168 +int main(int argc, char *argv[])
169 +{
170 + int ret;
171 + char *path = PTR_ALIGN_UP((char *)buf, SIZE);
172 + size_t start, end;
173 +
174 + setbuf(stdout, NULL);
175 +
176 + printf("some bad pointers\n");
177 + check_ptr(NULL);
178 + check_ptr((void *)-1);
179 +
180 + printf("lots of good pointers\n");
181 + printf(" buf = %p\n", buf);
182 + printf(" path = %p\n", path);
183 +
184 + for (start = 0; start < SIZE * 2 + STRIDE; start += STRIDE) {
185 + char *p = path + start;
186 + for (end = start + STRIDE; end < SIZE * 2 + STRIDE; end += STRIDE) {
187 + size_t len = end - start;
188 + printf(" open(%p -> %p [+%#zx])\n", p, p + len, len);
189 + memset(p, 'a', len);
190 + path[end] = '\0';
191 + ret = open(p, O_RDONLY);
192 + assert(ret == -1 && (errno == ENOENT || errno == ENAMETOOLONG));
193 + }
194 + }
195 +
196 + return 0;
197 +}