summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Wegener <swegener@gentoo.org>2009-10-31 15:40:14 +0000
committerSven Wegener <swegener@gentoo.org>2009-10-31 15:40:14 +0000
commit5de6406b8e29a1efcf6883f6ec016c429c42b526 (patch)
tree1aea26f05a2cf472326b84a0f16c0bac5d421093 /dev-util/systemtap
parentfix CHOST match for arm-boxes, thanks Markus Meier in bug #291289 (diff)
downloadgentoo-2-5de6406b8e29a1efcf6883f6ec016c429c42b526.tar.gz
gentoo-2-5de6406b8e29a1efcf6883f6ec016c429c42b526.tar.bz2
gentoo-2-5de6406b8e29a1efcf6883f6ec016c429c42b526.zip
Revision bump, security bug #290218.
(Portage version: 2.2_rc47/cvs/Linux x86_64)
Diffstat (limited to 'dev-util/systemtap')
-rw-r--r--dev-util/systemtap/ChangeLog10
-rw-r--r--dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-dwarf.patch125
-rw-r--r--dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-unwind.patch183
-rw-r--r--dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-varargs.patch64
-rw-r--r--dev-util/systemtap/systemtap-1.0-r1.ebuild57
5 files changed, 438 insertions, 1 deletions
diff --git a/dev-util/systemtap/ChangeLog b/dev-util/systemtap/ChangeLog
index 2cd26645b62c..48f4c80ef842 100644
--- a/dev-util/systemtap/ChangeLog
+++ b/dev-util/systemtap/ChangeLog
@@ -1,6 +1,14 @@
# ChangeLog for dev-util/systemtap
# Copyright 1999-2009 Gentoo Foundation; Distributed under the GPL v2
-# $Header: /var/cvsroot/gentoo-x86/dev-util/systemtap/ChangeLog,v 1.83 2009/09/28 19:29:36 swegener Exp $
+# $Header: /var/cvsroot/gentoo-x86/dev-util/systemtap/ChangeLog,v 1.84 2009/10/31 15:40:13 swegener Exp $
+
+*systemtap-1.0-r1 (31 Oct 2009)
+
+ 31 Oct 2009; Sven Wegener <swegener@gentoo.org> +systemtap-1.0-r1.ebuild,
+ +files/systemtap-1.0-CVE-2009-2911-dwarf.patch,
+ +files/systemtap-1.0-CVE-2009-2911-unwind.patch,
+ +files/systemtap-1.0-CVE-2009-2911-varargs.patch:
+ Revision bump, security bug #290218.
*systemtap-1.0 (28 Sep 2009)
diff --git a/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-dwarf.patch b/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-dwarf.patch
new file mode 100644
index 000000000000..d592ab32562e
--- /dev/null
+++ b/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-dwarf.patch
@@ -0,0 +1,125 @@
+https://bugzilla.redhat.com/show_bug.cgi?id=529175
+https://bugzilla.redhat.com/attachment.cgi?id=365294
+
+diff --git a/dwflpp.cxx b/dwflpp.cxx
+index 636cd38..c31548d 100644
+--- a/dwflpp.cxx
++++ b/dwflpp.cxx
+@@ -2272,7 +2272,15 @@ dwflpp::express_as_string (string prelude,
+
+ fprintf(memstream, "{\n");
+ fprintf(memstream, "%s", prelude.c_str());
+- bool deref = c_emit_location (memstream, head, 1);
++
++ unsigned int stack_depth;
++ bool deref = c_emit_location (memstream, head, 1, &stack_depth);
++
++ // Ensure that DWARF keeps loc2c to a "reasonable" stack size
++ // 32 intptr_t leads to max 256 bytes on the stack
++ if (stack_depth > 32)
++ throw semantic_error("oversized DWARF stack");
++
+ fprintf(memstream, "%s", postlude.c_str());
+ fprintf(memstream, " goto out;\n");
+
+diff --git a/loc2c-test.c b/loc2c-test.c
+index 495a95f..ed7aa4b 100644
+--- a/loc2c-test.c
++++ b/loc2c-test.c
+@@ -329,11 +329,14 @@ handle_variable (Dwarf_Die *lscopes, int lnscopes, int out,
+ "{\n"
+ " intptr_t value;");
+
+- bool deref = c_emit_location (stdout, head, 1);
++ unsigned int stack_depth;
++ bool deref = c_emit_location (stdout, head, 1, &stack_depth);
+
+ obstack_free (&pool, NULL);
+
+- puts (store ? " return;" :
++ printf (" /* max expression stack depth %u */\n", stack_depth);
++
++ puts (store ? " return;" :
+ " printk (\" ---> %ld\\n\", (unsigned long) value);\n"
+ " return;");
+
+diff --git a/loc2c.c b/loc2c.c
+index 5d6b549..0716c7d 100644
+--- a/loc2c.c
++++ b/loc2c.c
+@@ -2071,7 +2071,8 @@ emit_loc_address (FILE *out, struct location *loc, unsigned int indent,
+ assign it to an address-sized value. */
+ static void
+ emit_loc_value (FILE *out, struct location *loc, unsigned int indent,
+- const char *target, bool declare)
++ const char *target, bool declare,
++ bool *used_deref, unsigned int *max_stack)
+ {
+ if (declare)
+ emit ("%*s%s %s;\n", indent * 2, "", STACK_TYPE, target);
+@@ -2091,6 +2092,9 @@ emit_loc_value (FILE *out, struct location *loc, unsigned int indent,
+ case loc_address:
+ case loc_value:
+ emit_loc_address (out, loc, indent, target);
++ *used_deref = *used_deref || loc->address.used_deref;
++ if (loc->address.stack_depth > *max_stack)
++ *max_stack = loc->address.stack_depth;
+ break;
+ }
+
+@@ -2098,7 +2102,8 @@ emit_loc_value (FILE *out, struct location *loc, unsigned int indent,
+ }
+
+ bool
+-c_emit_location (FILE *out, struct location *loc, int indent)
++c_emit_location (FILE *out, struct location *loc, int indent,
++ unsigned int *max_stack)
+ {
+ emit ("%*s{\n", indent * 2, "");
+
+@@ -2134,9 +2139,11 @@ c_emit_location (FILE *out, struct location *loc, int indent)
+ }
+
+ bool deref = false;
++ *max_stack = 0;
+
+ if (loc->frame_base != NULL)
+- emit_loc_value (out, loc->frame_base, indent, "frame_base", true);
++ emit_loc_value (out, loc->frame_base, indent, "frame_base", true,
++ &deref, max_stack);
+
+ for (; loc->next != NULL; loc = loc->next)
+ switch (loc->type)
+@@ -2144,8 +2151,7 @@ c_emit_location (FILE *out, struct location *loc, int indent)
+ case loc_address:
+ case loc_value:
+ /* Emit the program fragment to calculate the address. */
+- emit_loc_value (out, loc, indent + 1, "addr", false);
+- deref = deref || loc->address.used_deref;
++ emit_loc_value (out, loc, indent + 1, "addr", false, &deref, max_stack);
+ break;
+
+ case loc_fragment:
+@@ -2172,6 +2178,9 @@ c_emit_location (FILE *out, struct location *loc, int indent)
+
+ emit ("%s%*s}\n", loc->address.program, indent * 2, "");
+
++ if (loc->address.stack_depth > *max_stack)
++ *max_stack = loc->address.stack_depth;
++
+ return deref || loc->address.used_deref;
+ }
+
+diff --git a/loc2c.h b/loc2c.h
+index becf2d8..45d9382 100644
+--- a/loc2c.h
++++ b/loc2c.h
+@@ -112,6 +112,7 @@ struct location *c_translate_argument (struct obstack *,
+
+ Writes complete lines of C99, code forming a complete C block, to STREAM.
+ Return value is true iff that code uses the `deref' runtime macros. */
+-bool c_emit_location (FILE *stream, struct location *loc, int indent);
++bool c_emit_location (FILE *stream, struct location *loc, int indent,
++ unsigned int *max_stack);
+
+ /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-unwind.patch b/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-unwind.patch
new file mode 100644
index 000000000000..f2f1aa4ee75c
--- /dev/null
+++ b/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-unwind.patch
@@ -0,0 +1,183 @@
+https://bugzilla.redhat.com/show_bug.cgi?id=529175
+https://bugzilla.redhat.com/attachment.cgi?id=365413
+
+diff --git a/runtime/unwind.c b/runtime/unwind.c
+index 00108a3..7607770 100644
+--- a/runtime/unwind.c
++++ b/runtime/unwind.c
+@@ -88,7 +88,7 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
+
+ /* given an FDE, find its CIE */
+ static const u32 *cie_for_fde(const u32 *fde, void *unwind_data,
+- int is_ehframe)
++ uint32_t table_len, int is_ehframe)
+ {
+ const u32 *cie;
+
+@@ -118,6 +118,11 @@ static const u32 *cie_for_fde(const u32 *fde, void *unwind_data,
+ else
+ cie = unwind_data + fde[1];
+
++ /* Make sure address falls in the table */
++ if (((void *)cie) < ((void*)unwind_data)
++ || ((void*)cie) > ((void*)(unwind_data + table_len)))
++ return NULL;
++
+ if (*cie <= sizeof(*cie) + 4 || *cie >= fde[1] - sizeof(*fde)
+ || (*cie & (sizeof(*cie) - 1))
+ || (cie[1] != 0xffffffff && cie[1] != 0)) {
+@@ -200,7 +205,8 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end, signed ptrTy
+ return value;
+ }
+
+-static signed fde_pointer_type(const u32 *cie)
++static signed fde_pointer_type(const u32 *cie, void *unwind_data,
++ uint32_t table_len)
+ {
+ const u8 *ptr = (const u8 *)(cie + 2);
+ unsigned version = *ptr;
+@@ -212,11 +218,16 @@ static signed fde_pointer_type(const u32 *cie)
+ const u8 *end = (const u8 *)(cie + 1) + *cie;
+ uleb128_t len;
+
++ /* end of cie should fall within unwind table. */
++ if (((void*)end) < ((void *)unwind_data)
++ || ((void *)end) > ((void *)(unwind_data + table_len)))
++ return -1;
++
+ /* check if augmentation size is first (and thus present) */
+ if (*ptr != 'z')
+ return -1;
+ /* check if augmentation string is nul-terminated */
+- if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
++ if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL)
+ return -1;
+ ++ptr; /* skip terminator */
+ get_uleb128(&ptr, end); /* skip code alignment */
+@@ -267,6 +278,10 @@ static void set_rule(uleb128_t reg, enum item_location where, uleb128_t value, s
+ }
+ }
+
++/* Limit the number of instructions we process. Arbitrary limit.
++ 512 should be enough for anybody... */
++#define MAX_CFI 512
++
+ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, signed ptrType, struct unwind_state *state)
+ {
+ union {
+@@ -276,6 +291,9 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, s
+ } ptr;
+ int result = 1;
+
++ if (end - start > MAX_CFI)
++ return 0;
++
+ dbug_unwind(1, "targetLoc=%lx state->loc=%lx\n", targetLoc, state->loc);
+ if (start != state->cieStart) {
+ state->loc = state->org;
+@@ -606,10 +624,10 @@ static int unwind_frame(struct unwind_frame_info *frame,
+
+ /* found the fde, now set startLoc and endLoc */
+ if (fde != NULL) {
+- cie = cie_for_fde(fde, table, is_ehframe);
++ cie = cie_for_fde(fde, table, table_len, is_ehframe);
+ if (likely(cie != NULL && cie != &bad_cie && cie != &not_fde)) {
+ ptr = (const u8 *)(fde + 2);
+- ptrType = fde_pointer_type(cie);
++ ptrType = fde_pointer_type(cie, table, table_len);
+ startLoc = read_pointer(&ptr, (const u8 *)(fde + 1) + *fde, ptrType);
+ startLoc = adjustStartLoc(startLoc, m, s, ptrType, is_ehframe);
+
+@@ -632,12 +650,12 @@ static int unwind_frame(struct unwind_frame_info *frame,
+ for (fde = table, tableSize = table_len; cie = NULL, tableSize > sizeof(*fde)
+ && tableSize - sizeof(*fde) >= *fde; tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) {
+ dbug_unwind(3, "fde=%lx tableSize=%d\n", (long)*fde, (int)tableSize);
+- cie = cie_for_fde(fde, table, is_ehframe);
++ cie = cie_for_fde(fde, table, table_len, is_ehframe);
+ if (cie == &bad_cie) {
+ cie = NULL;
+ break;
+ }
+- if (cie == NULL || cie == &not_fde || (ptrType = fde_pointer_type(cie)) < 0)
++ if (cie == NULL || cie == &not_fde || (ptrType = fde_pointer_type(cie, table, table_len)) < 0)
+ continue;
+
+ ptr = (const u8 *)(fde + 2);
+@@ -666,6 +684,12 @@ static int unwind_frame(struct unwind_frame_info *frame,
+ state.cieEnd = ptr; /* keep here temporarily */
+ ptr = (const u8 *)(cie + 2);
+ end = (const u8 *)(cie + 1) + *cie;
++
++ /* end should fall within unwind table. */
++ if (((void *)end) < table
++ || ((void *)end) > ((void *)(table + table_len)))
++ goto err;
++
+ frame->call_frame = 1;
+ if ((state.version = *ptr) != 1) {
+ dbug_unwind(1, "CIE version number is %d. 1 is supported.\n", state.version);
+@@ -723,6 +747,11 @@ static int unwind_frame(struct unwind_frame_info *frame,
+ state.cieEnd = end;
+ end = (const u8 *)(fde + 1) + *fde;
+
++ /* end should fall within unwind table. */
++ if (((void*)end) < table
++ || ((void *)end) > ((void *)(table + table_len)))
++ goto err;
++
+ /* skip augmentation */
+ if (((const char *)(cie + 2))[1] == 'z') {
+ uleb128_t augSize = get_uleb128(&ptr, end);
+diff --git a/runtime/unwind/unwind.h b/runtime/unwind/unwind.h
+index 285a3a3..023ea60 100644
+--- a/runtime/unwind/unwind.h
++++ b/runtime/unwind/unwind.h
+@@ -143,8 +143,10 @@ static unsigned long read_pointer(const u8 **pLoc,
+ const void *end,
+ signed ptrType);
+ static const u32 bad_cie, not_fde;
+-static const u32 *cie_for_fde(const u32 *fde, void *table, int is_ehframe);
+-static signed fde_pointer_type(const u32 *cie);
++static const u32 *cie_for_fde(const u32 *fde, void *table,
++ uint32_t table_len, int is_ehframe);
++static signed fde_pointer_type(const u32 *cie,
++ void *table, uint32_t table_len);
+
+
+ #endif /* STP_USE_DWARF_UNWINDER */
+diff --git a/translate.cxx b/translate.cxx
+index bc5d615..9d456bc 100644
+--- a/translate.cxx
++++ b/translate.cxx
+@@ -29,6 +29,11 @@ extern "C" {
+ #include <elfutils/libdwfl.h>
+ }
+
++// Max unwind table size (debug or eh) per module. Somewhat arbitrary
++// limit (a bit more than twice the .debug_frame size of my local
++// vmlinux for 2.6.31.4-83.fc12.x86_64)
++#define MAX_UNWIND_TABLE_SIZE (3 * 1024 * 1024)
++
+ using namespace std;
+
+ struct var;
+@@ -4785,6 +4790,9 @@ dump_unwindsyms (Dwfl_Module *m,
+ get_unwind_data (m, &debug_frame, &eh_frame, &debug_len, &eh_len, &eh_addr);
+ if (debug_frame != NULL && debug_len > 0)
+ {
++ if (debug_len > MAX_UNWIND_TABLE_SIZE)
++ throw semantic_error ("module debug unwind table size too big");
++
+ c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
+ c->output << "static uint8_t _stp_module_" << stpmod_idx
+ << "_debug_frame[] = \n";
+@@ -4802,6 +4810,9 @@ dump_unwindsyms (Dwfl_Module *m,
+
+ if (eh_frame != NULL && eh_len > 0)
+ {
++ if (eh_len > MAX_UNWIND_TABLE_SIZE)
++ throw semantic_error ("module eh unwind table size too big");
++
+ c->output << "#if defined(STP_USE_DWARF_UNWINDER) && defined(STP_NEED_UNWIND_DATA)\n";
+ c->output << "static uint8_t _stp_module_" << stpmod_idx
+ << "_eh_frame[] = \n";
diff --git a/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-varargs.patch b/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-varargs.patch
new file mode 100644
index 000000000000..77c43ca2e8d7
--- /dev/null
+++ b/dev-util/systemtap/files/systemtap-1.0-CVE-2009-2911-varargs.patch
@@ -0,0 +1,64 @@
+https://bugzilla.redhat.com/show_bug.cgi?id=529175
+https://bugzilla.redhat.com/attachment.cgi?id=365293
+
+diff --git a/buildrun.cxx b/buildrun.cxx
+index 100cbc4..c86a442 100644
+--- a/buildrun.cxx
++++ b/buildrun.cxx
+@@ -200,6 +200,9 @@ compile_pass (systemtap_session& s)
+
+ // o << "CFLAGS += -fno-unit-at-a-time" << endl;
+
++ // 512 bytes should be enough for anybody
++ o << "EXTRA_CFLAGS += $(call cc-option,-Wframe-larger-than=512)" << endl;
++
+ // Assumes linux 2.6 kbuild
+ o << "EXTRA_CFLAGS += -Wno-unused -Werror" << endl;
+ #if CHECK_POINTER_ARITH_PR5947
+diff --git a/testsuite/transko/varargs.stp b/testsuite/transko/varargs.stp
+new file mode 100755
+index 0000000..f38309a
+--- /dev/null
++++ b/testsuite/transko/varargs.stp
+@@ -0,0 +1,10 @@
++#! stap -p3
++
++probe begin {
++ // PR10750 enforces at most 32 print args
++ println(1, 2, 3, 4, 5, 6, 7, 8,
++ 9, 10, 11, 12, 13, 14, 15, 16,
++ 17, 18, 19, 20, 21, 22, 23, 24,
++ 25, 26, 27, 28, 29, 30, 31, 32,
++ 33)
++}
+diff --git a/testsuite/transok/varargs.stp b/testsuite/transok/varargs.stp
+new file mode 100755
+index 0000000..216166f
+--- /dev/null
++++ b/testsuite/transok/varargs.stp
+@@ -0,0 +1,9 @@
++#! stap -p3
++
++probe begin {
++ // PR10750 enforces at most 32 print args
++ println(1, 2, 3, 4, 5, 6, 7, 8,
++ 9, 10, 11, 12, 13, 14, 15, 16,
++ 17, 18, 19, 20, 21, 22, 23, 24,
++ 25, 26, 27, 28, 29, 30, 31, 32)
++}
+diff --git a/translate.cxx b/translate.cxx
+index 04a9247..c73a5bd 100644
+--- a/translate.cxx
++++ b/translate.cxx
+@@ -4151,6 +4151,11 @@ c_unparser::visit_print_format (print_format* e)
+ {
+ stmt_expr block(*this);
+
++ // PR10750: Enforce a reasonable limit on # of varargs
++ // 32 varargs leads to max 256 bytes on the stack
++ if (e->args.size() > 32)
++ throw semantic_error("too many arguments to print", e->tok);
++
+ // Compute actual arguments
+ vector<tmpvar> tmp;
+
diff --git a/dev-util/systemtap/systemtap-1.0-r1.ebuild b/dev-util/systemtap/systemtap-1.0-r1.ebuild
new file mode 100644
index 000000000000..f075570718ff
--- /dev/null
+++ b/dev-util/systemtap/systemtap-1.0-r1.ebuild
@@ -0,0 +1,57 @@
+# Copyright 1999-2009 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Header: /var/cvsroot/gentoo-x86/dev-util/systemtap/systemtap-1.0-r1.ebuild,v 1.1 2009/10/31 15:40:13 swegener Exp $
+
+EAPI="2"
+
+inherit linux-info eutils
+
+DESCRIPTION="A linux trace/probe tool"
+HOMEPAGE="http://sourceware.org/systemtap/"
+if [[ ${PV} = *_p* ]] # is this a snaphot?
+then
+ # see configure.ac to get the version of the snapshot
+ SRC_URI="http://sources.redhat.com/${PN}/ftp/snapshots/${PN}-${PV/*_p/}.tar.bz2
+ mirror://gentoo/${PN}-${PV/*_p/}.tar.bz2" # upstream only keeps four snapshot distfiles around
+ S="${WORKDIR}"/src
+else
+ SRC_URI="http://sources.redhat.com/${PN}/ftp/releases/${P}.tar.gz"
+ # use default S for releases
+fi
+
+LICENSE="GPL-2"
+SLOT="0"
+KEYWORDS="~amd64 ~x86"
+IUSE="sqlite"
+
+DEPEND=">=dev-libs/elfutils-0.142
+ sys-libs/libcap
+ sqlite? ( =dev-db/sqlite-3* )"
+RDEPEND="${DEPEND}
+ virtual/linux-sources"
+
+CONFIG_CHECK="~KPROBES ~RELAY ~DEBUG_FS"
+ERROR_KPROBES="${PN} requires support for KProbes Instrumentation (KPROBES) - this can be enabled in 'Instrumentation Support -> Kprobes'."
+ERROR_RELAY="${PN} works with support for user space relay support (RELAY) - this can be enabled in 'General setup -> Kernel->user space relay support (formerly relayfs)'."
+ERROR_DEBUG_FS="${PN} works best with support for Debug Filesystem (DEBUG_FS) - this can be enabled in 'Kernel hacking -> Debug Filesystem'."
+
+src_prepare() {
+ epatch "${FILESDIR}"/${P}-CVE-2009-2911-{varargs,dwarf,unwind}.patch
+}
+
+src_configure() {
+ econf \
+ --docdir=/usr/share/doc/${PF} \
+ --without-rpm \
+ --disable-server \
+ --disable-docs \
+ --disable-refdocs \
+ --disable-grapher \
+ $(use_enable sqlite) \
+ || die "econf failed"
+}
+
+src_install() {
+ emake install DESTDIR="${D}" || die "make install failed"
+ dodoc AUTHORS HACKING NEWS README
+}