Gentoo Archives: gentoo-commits

From: "Sven Wegener (swegener)" <swegener@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in dev-util/systemtap/files: systemtap-1.0-CVE-2009-2911-dwarf.patch systemtap-1.0-CVE-2009-2911-varargs.patch systemtap-1.0-CVE-2009-2911-unwind.patch
Date: Sat, 31 Oct 2009 15:40:18
Message-Id: E1N4G3r-0001dF-CS@stork.gentoo.org
1 swegener 09/10/31 15:40:15
2
3 Added: systemtap-1.0-CVE-2009-2911-dwarf.patch
4 systemtap-1.0-CVE-2009-2911-varargs.patch
5 systemtap-1.0-CVE-2009-2911-unwind.patch
6 Log:
7 Revision bump, security bug #290218.
8 (Portage version: 2.2_rc47/cvs/Linux x86_64)
9
10 Revision Changes Path
11 1.1 dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-dwarf.patch
12
13 file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-dwarf.patch?rev=1.1&view=markup
14 plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-dwarf.patch?rev=1.1&content-type=text/plain
15
16 Index: systemtap-1.0-CVE-2009-2911-dwarf.patch
17 ===================================================================
18 https://bugzilla.redhat.com/show_bug.cgi?id=529175
19 https://bugzilla.redhat.com/attachment.cgi?id=365294
20
21 diff --git a/dwflpp.cxx b/dwflpp.cxx
22 index 636cd38..c31548d 100644
23 --- a/dwflpp.cxx
24 +++ b/dwflpp.cxx
25 @@ -2272,7 +2272,15 @@ dwflpp::express_as_string (string prelude,
26
27 fprintf(memstream, "{\n");
28 fprintf(memstream, "%s", prelude.c_str());
29 - bool deref = c_emit_location (memstream, head, 1);
30 +
31 + unsigned int stack_depth;
32 + bool deref = c_emit_location (memstream, head, 1, &stack_depth);
33 +
34 + // Ensure that DWARF keeps loc2c to a "reasonable" stack size
35 + // 32 intptr_t leads to max 256 bytes on the stack
36 + if (stack_depth > 32)
37 + throw semantic_error("oversized DWARF stack");
38 +
39 fprintf(memstream, "%s", postlude.c_str());
40 fprintf(memstream, " goto out;\n");
41
42 diff --git a/loc2c-test.c b/loc2c-test.c
43 index 495a95f..ed7aa4b 100644
44 --- a/loc2c-test.c
45 +++ b/loc2c-test.c
46 @@ -329,11 +329,14 @@ handle_variable (Dwarf_Die *lscopes, int lnscopes, int out,
47 "{\n"
48 " intptr_t value;");
49
50 - bool deref = c_emit_location (stdout, head, 1);
51 + unsigned int stack_depth;
52 + bool deref = c_emit_location (stdout, head, 1, &stack_depth);
53
54 obstack_free (&pool, NULL);
55
56 - puts (store ? " return;" :
57 + printf (" /* max expression stack depth %u */\n", stack_depth);
58 +
59 + puts (store ? " return;" :
60 " printk (\" ---> %ld\\n\", (unsigned long) value);\n"
61 " return;");
62
63 diff --git a/loc2c.c b/loc2c.c
64 index 5d6b549..0716c7d 100644
65 --- a/loc2c.c
66 +++ b/loc2c.c
67 @@ -2071,7 +2071,8 @@ emit_loc_address (FILE *out, struct location *loc, unsigned int indent,
68 assign it to an address-sized value. */
69 static void
70 emit_loc_value (FILE *out, struct location *loc, unsigned int indent,
71 - const char *target, bool declare)
72 + const char *target, bool declare,
73 + bool *used_deref, unsigned int *max_stack)
74 {
75 if (declare)
76 emit ("%*s%s %s;\n", indent * 2, "", STACK_TYPE, target);
77 @@ -2091,6 +2092,9 @@ emit_loc_value (FILE *out, struct location *loc, unsigned int indent,
78 case loc_address:
79 case loc_value:
80 emit_loc_address (out, loc, indent, target);
81 + *used_deref = *used_deref || loc->address.used_deref;
82 + if (loc->address.stack_depth > *max_stack)
83 + *max_stack = loc->address.stack_depth;
84 break;
85 }
86
87 @@ -2098,7 +2102,8 @@ emit_loc_value (FILE *out, struct location *loc, unsigned int indent,
88 }
89
90 bool
91 -c_emit_location (FILE *out, struct location *loc, int indent)
92 +c_emit_location (FILE *out, struct location *loc, int indent,
93 + unsigned int *max_stack)
94 {
95 emit ("%*s{\n", indent * 2, "");
96
97 @@ -2134,9 +2139,11 @@ c_emit_location (FILE *out, struct location *loc, int indent)
98 }
99
100 bool deref = false;
101 + *max_stack = 0;
102
103 if (loc->frame_base != NULL)
104 - emit_loc_value (out, loc->frame_base, indent, "frame_base", true);
105 + emit_loc_value (out, loc->frame_base, indent, "frame_base", true,
106 + &deref, max_stack);
107
108 for (; loc->next != NULL; loc = loc->next)
109 switch (loc->type)
110 @@ -2144,8 +2151,7 @@ c_emit_location (FILE *out, struct location *loc, int indent)
111 case loc_address:
112 case loc_value:
113 /* Emit the program fragment to calculate the address. */
114 - emit_loc_value (out, loc, indent + 1, "addr", false);
115 - deref = deref || loc->address.used_deref;
116 + emit_loc_value (out, loc, indent + 1, "addr", false, &deref, max_stack);
117 break;
118
119 case loc_fragment:
120 @@ -2172,6 +2178,9 @@ c_emit_location (FILE *out, struct location *loc, int indent)
121
122 emit ("%s%*s}\n", loc->address.program, indent * 2, "");
123
124 + if (loc->address.stack_depth > *max_stack)
125 + *max_stack = loc->address.stack_depth;
126 +
127 return deref || loc->address.used_deref;
128 }
129
130 diff --git a/loc2c.h b/loc2c.h
131 index becf2d8..45d9382 100644
132 --- a/loc2c.h
133 +++ b/loc2c.h
134 @@ -112,6 +112,7 @@ struct location *c_translate_argument (struct obstack *,
135
136 Writes complete lines of C99, code forming a complete C block, to STREAM.
137 Return value is true iff that code uses the `deref' runtime macros. */
138 -bool c_emit_location (FILE *stream, struct location *loc, int indent);
139 +bool c_emit_location (FILE *stream, struct location *loc, int indent,
140 + unsigned int *max_stack);
141
142 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
143
144
145
146 1.1 dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-varargs.patch
147
148 file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-varargs.patch?rev=1.1&view=markup
149 plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-varargs.patch?rev=1.1&content-type=text/plain
150
151 Index: systemtap-1.0-CVE-2009-2911-varargs.patch
152 ===================================================================
153 https://bugzilla.redhat.com/show_bug.cgi?id=529175
154 https://bugzilla.redhat.com/attachment.cgi?id=365293
155
156 diff --git a/buildrun.cxx b/buildrun.cxx
157 index 100cbc4..c86a442 100644
158 --- a/buildrun.cxx
159 +++ b/buildrun.cxx
160 @@ -200,6 +200,9 @@ compile_pass (systemtap_session& s)
161
162 // o << "CFLAGS += -fno-unit-at-a-time" << endl;
163
164 + // 512 bytes should be enough for anybody
165 + o << "EXTRA_CFLAGS += $(call cc-option,-Wframe-larger-than=512)" << endl;
166 +
167 // Assumes linux 2.6 kbuild
168 o << "EXTRA_CFLAGS += -Wno-unused -Werror" << endl;
169 #if CHECK_POINTER_ARITH_PR5947
170 diff --git a/testsuite/transko/varargs.stp b/testsuite/transko/varargs.stp
171 new file mode 100755
172 index 0000000..f38309a
173 --- /dev/null
174 +++ b/testsuite/transko/varargs.stp
175 @@ -0,0 +1,10 @@
176 +#! stap -p3
177 +
178 +probe begin {
179 + // PR10750 enforces at most 32 print args
180 + println(1, 2, 3, 4, 5, 6, 7, 8,
181 + 9, 10, 11, 12, 13, 14, 15, 16,
182 + 17, 18, 19, 20, 21, 22, 23, 24,
183 + 25, 26, 27, 28, 29, 30, 31, 32,
184 + 33)
185 +}
186 diff --git a/testsuite/transok/varargs.stp b/testsuite/transok/varargs.stp
187 new file mode 100755
188 index 0000000..216166f
189 --- /dev/null
190 +++ b/testsuite/transok/varargs.stp
191 @@ -0,0 +1,9 @@
192 +#! stap -p3
193 +
194 +probe begin {
195 + // PR10750 enforces at most 32 print args
196 + println(1, 2, 3, 4, 5, 6, 7, 8,
197 + 9, 10, 11, 12, 13, 14, 15, 16,
198 + 17, 18, 19, 20, 21, 22, 23, 24,
199 + 25, 26, 27, 28, 29, 30, 31, 32)
200 +}
201 diff --git a/translate.cxx b/translate.cxx
202 index 04a9247..c73a5bd 100644
203 --- a/translate.cxx
204 +++ b/translate.cxx
205 @@ -4151,6 +4151,11 @@ c_unparser::visit_print_format (print_format* e)
206 {
207 stmt_expr block(*this);
208
209 + // PR10750: Enforce a reasonable limit on # of varargs
210 + // 32 varargs leads to max 256 bytes on the stack
211 + if (e->args.size() > 32)
212 + throw semantic_error("too many arguments to print", e->tok);
213 +
214 // Compute actual arguments
215 vector<tmpvar> tmp;
216
217
218
219
220 1.1 dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-unwind.patch
221
222 file : http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-unwind.patch?rev=1.1&view=markup
223 plain: http://sources.gentoo.org/viewcvs.py/gentoo-x86/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-unwind.patch?rev=1.1&content-type=text/plain
224
225 Index: systemtap-1.0-CVE-2009-2911-unwind.patch
226 ===================================================================
227 https://bugzilla.redhat.com/show_bug.cgi?id=529175
228 https://bugzilla.redhat.com/attachment.cgi?id=365413
229
230 diff --git a/runtime/unwind.c b/runtime/unwind.c
231 index 00108a3..7607770 100644
232 --- a/runtime/unwind.c
233 +++ b/runtime/unwind.c
234 @@ -88,7 +88,7 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
235
236 /* given an FDE, find its CIE */
237 static const u32 *cie_for_fde(const u32 *fde, void *unwind_data,
238 - int is_ehframe)
239 + uint32_t table_len, int is_ehframe)
240 {
241 const u32 *cie;
242
243 @@ -118,6 +118,11 @@ static const u32 *cie_for_fde(const u32 *fde, void *unwind_data,
244 else
245 cie = unwind_data + fde[1];
246
247 + /* Make sure address falls in the table */
248 + if (((void *)cie) < ((void*)unwind_data)
249 + || ((void*)cie) > ((void*)(unwind_data + table_len)))
250 + return NULL;
251 +
252 if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
253 || (*cie & (sizeof(*cie) - 1))
254 || (cie[1] != 0xffffffff && cie[1] != 0)) {
255 @@ -200,7 +205,8 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end, signed ptrTy
256 return value;
257 }
258
259 -static signed fde_pointer_type(const u32 *cie)
260 +static signed fde_pointer_type(const u32 *cie, void *unwind_data,
261 + uint32_t table_len)
262 {
263 const u8 *ptr = (const u8 *)(cie + 2);
264 unsigned version = *ptr;
265 @@ -212,11 +218,16 @@ static signed fde_pointer_type(const u32 *cie)
266 const u8 *end = (const u8 *)(cie + 1) + *cie;
267 uleb128_t len;
268
269 + /* end of cie should fall within unwind table. */
270 + if (((void*)end) < ((void *)unwind_data)
271 + || ((void *)end) > ((void *)(unwind_data + table_len)))
272 + return -1;
273 +
274 /* check if augmentation size is first (and thus present) */
275 if (*ptr != 'z')
276 return -1;
277 /* check if augmentation string is nul-terminated */
278 - if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
279 + if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
280 return -1;
281 ++ptr; /* skip terminator */
282 get_uleb128(&ptr, end); /* skip code alignment */
283 @@ -267,6 +278,10 @@ static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value, s
284 }
285 }
286
287 +/* Limit the number of instructions we process. Arbitrary limit.
288 + 512 should be enough for anybody... */
289 +#define MAX_CFI 512
290 +
291 static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, signed ptrType, struct unwind_state *state)
292 {
293 union {
294 @@ -276,6 +291,9 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, s
295 } ptr;
296 int result = 1;
297
298 + if (end - start > MAX_CFI)
299 + return 0;
300 +
301 dbug_unwind(1, "targetLoc=%lx state->loc=%lx\n", targetLoc, state->loc);
302 if (start != state->cieStart) {
303 state->loc = state->org;
304 @@ -606,10 +624,10 @@ static int unwind_frame(struct unwind_frame_info *frame,
305
306 /* found the fde, now set startLoc and endLoc */
307 if (fde != NULL) {
308 - cie = cie_for_fde(fde, table, is_ehframe);
309 + cie = cie_for_fde(fde, table, table_len, is_ehframe);
310 if (likely(cie != NULL && cie != &bad_cie && cie != &not_fde)) {
311 ptr = (const u8 *)(fde + 2);
312 - ptrType = fde_pointer_type(cie);
313 + ptrType = fde_pointer_type(cie, table, table_len);
314 startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType);
315 startLoc = adjustStartLoc(startLoc, m, s, ptrType, is_ehframe);
316
317 @@ -632,12 +650,12 @@ static int unwind_frame(struct unwind_frame_info *frame,
318 for (fde = table, tableSize = table_len; cie = NULL, tableSize > sizeof(*fde)
319 && tableSize - sizeof(*fde) >= *fde; tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
320 dbug_unwind(3, "fde=%lx tableSize=%d\n", (long)*fde, (int)tableSize);
321 - cie = cie_for_fde(fde, table, is_ehframe);
322 + cie = cie_for_fde(fde, table, table_len, is_ehframe);
323 if (cie == &bad_cie) {
324 cie = NULL;
325 break;
326 }
327 - if (cie == NULL || cie == &not_fde || (ptrType = fde_pointer_type(cie)) < 0)
328 + if (cie == NULL || cie == &not_fde || (ptrType = fde_pointer_type(cie, table, table_len)) < 0)
329 continue;
330
331 ptr = (const u8 *)(fde + 2);
332 @@ -666,6 +684,12 @@ static int unwind_frame(struct unwind_frame_info *frame,
333 state.cieEnd = ptr; /* keep here temporarily */
334 ptr = (const u8 *)(cie + 2);
335 end = (const u8 *)(cie + 1) + *cie;
336 +
337 + /* end should fall within unwind table. */
338 + if (((void *)end) < table
339 + || ((void *)end) > ((void *)(table + table_len)))
340 + goto err;
341 +
342 frame->call_frame = 1;
343 if ((state.version = *ptr) != 1) {
344 dbug_unwind(1, "CIE version number is %d. 1 is supported.\n", state.version);
345 @@ -723,6 +747,11 @@ static int unwind_frame(struct unwind_frame_info *frame,
346 state.cieEnd = end;
347 end = (const u8 *)(fde + 1) + *fde;
348
349 + /* end should fall within unwind table. */
350 + if (((void*)end) < table
351 + || ((void *)end) > ((void *)(table + table_len)))
352 + goto err;
353 +
354 /* skip augmentation */
355 if (((const char *)(cie + 2))[1] == 'z') {
356 uleb128_t augSize = get_uleb128(&ptr, end);
357 diff --git a/runtime/unwind/unwind.h b/runtime/unwind/unwind.h
358 index 285a3a3..023ea60 100644
359 --- a/runtime/unwind/unwind.h
360 +++ b/runtime/unwind/unwind.h
361 @@ -143,8 +143,10 @@ static unsigned long read_pointer(const u8 **pLoc,
362 const void *end,
363 signed ptrType);
364 static const u32 bad_cie, not_fde;
365 -static const u32 *cie_for_fde(const u32 *fde, void *table, int is_ehframe);
366 -static signed fde_pointer_type(const u32 *cie);
367 +static const u32 *cie_for_fde(const u32 *fde, void *table,
368 + uint32_t table_len, int is_ehframe);
369 +static signed fde_pointer_type(const u32 *cie,
370 + void *table, uint32_t table_len);
371
372
373 #endif /* STP_USE_DWARF_UNWINDER */
374 diff --git a/translate.cxx b/translate.cxx
375 index bc5d615..9d456bc 100644
376 --- a/translate.cxx
377 +++ b/translate.cxx
378 @@ -29,6 +29,11 @@ extern "C" {
379 #include <elfutils/libdwfl.h>
380 }
381
382 +// Max unwind table size (debug or eh) per module. Somewhat arbitrary
383 +// limit (a bit more than twice the .debug_frame size of my local
384 +// vmlinux for 2.6.31.4-83.fc12.x86_64)
385 +#define MAX_UNWIND_TABLE_SIZE (3 * 1024 * 1024)
386 +
387 using namespace std;
388
389 struct var;
390 @@ -4785,6 +4790,9 @@ dump_unwindsyms (Dwfl_Module *m,
391 get_unwind_data (m, &debug_frame, &eh_frame, &debug_len, &eh_len, &eh_addr);
392 if (debug_frame != NULL && debug_len > 0)
393 {
394 + if (debug_len > MAX_UNWIND_TABLE_SIZE)
395 + throw semantic_error ("module debug unwind table size too big");
396 +
397 c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
398 c->output << "static uint8_t _stp_module_" << stpmod_idx
399 << "_debug_frame[] = \n";
400 @@ -4802,6 +4810,9 @@ dump_unwindsyms (Dwfl_Module *m,
401
402 if (eh_frame != NULL && eh_len > 0)
403 {
404 + if (eh_len > MAX_UNWIND_TABLE_SIZE)
405 + throw semantic_error ("module eh unwind table size too big");
406 +
407 c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
408 c->output << "static uint8_t _stp_module_" << stpmod_idx
409 << "_eh_frame[] = \n";