From 9860042ecbb5d2ec33249198d9bb3543ffab2565 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 18 May 2011 16:45:11 -0400 Subject: [PATCH] CVE-2011-1781, CVE-2011-1769: correct DW_OP_{mod,div} division-by-zero bug --- bz702687.patch | 129 +++++++++++++++++++++++++++++++++++++++++++++++++ systemtap.spec | 7 ++- 2 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 bz702687.patch diff --git a/bz702687.patch b/bz702687.patch new file mode 100644 index 0000000..db47133 --- /dev/null +++ b/bz702687.patch @@ -0,0 +1,129 @@ +commit fa2e3415185a28542d419a641ecd6cddd52e3cd9 +Author: Mark Wielaard +Date: Wed May 11 15:27:48 2011 -0400 + + CVE-2011-1781, CVE-2011-1769: correct DW_OP_{mod,div} division-by-zero bug + + Probing a process with corrupted DWARF information, it has been + possible to create a kernel-side divison-by-zero. This fixes. + + Handle DW_OP_div/mod divide by zero. DW_OP_mod should work unsigned. + + * loc2c.c (translate): Use helper functions div_op and mod_op for + DW_OP_div and DW_OP_mod operands. Set used_deref = true. + * translate.cxx (translate_runtime): Emit STAP_MSG_LOC2C_03 define. + * runtime/loc2c-runtime.h: Define dwarf_div_op and dwarf_mod_op macros. + * runtime/unwind.c (compute_expr): Check for zero before executing + DW_OP_mod or DW_OP_div. + +diff --git a/loc2c.c b/loc2c.c +index 331090c..5f0dd09 100644 +--- a/loc2c.c ++++ b/loc2c.c +@@ -681,7 +681,6 @@ translate (struct location_context *ctx, int indent, + UNOP (abs, op_abs); + BINOP (and, &); + BINOP (minus, -); +- BINOP (mod, %); + BINOP (mul, *); + UNOP (neg, -); + UNOP (not, ~); +@@ -716,9 +715,21 @@ translate (struct location_context *ctx, int indent, + { + POP (b); + POP (a); +- push ("(%s) " STACKFMT " / (%s)" STACKFMT, ++ push ("dwarf_div_op((%s) " STACKFMT ", (%s) " STACKFMT ")", + stack_slot_type (loc, true), a, + stack_slot_type (loc, true), b); ++ used_deref = true; ++ break; ++ } ++ ++ case DW_OP_mod: ++ { ++ POP (b); ++ POP (a); ++ push ("dwarf_mod_op((%s) " STACKFMT ", (%s) " STACKFMT ")", ++ stack_slot_type (loc, false), a, ++ stack_slot_type (loc, false), b); ++ used_deref = true; + break; + } + +diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h +index d511087..968045f 100644 +--- a/runtime/loc2c-runtime.h ++++ b/runtime/loc2c-runtime.h +@@ -82,6 +82,28 @@ + }) + #endif + ++/* dwarf_div_op and dwarf_mod_op do division and modulo operations catching any ++ divide by zero issues. When they detect div_by_zero they "fault" ++ by jumping to the (slightly misnamed) deref_fault label. */ ++#define dwarf_div_op(a,b) ({ \ ++ if (b == 0) { \ ++ snprintf(c->error_buffer, sizeof(c->error_buffer), \ ++ "divide by zero in DWARF operand (%s)", "DW_OP_div"); \ ++ c->last_error = c->error_buffer; \ ++ goto deref_fault; \ ++ } \ ++ a / b; \ ++}) ++#define dwarf_mod_op(a,b) ({ \ ++ if (b == 0) { \ ++ snprintf(c->error_buffer, sizeof(c->error_buffer), \ ++ "divide by zero in DWARF operand (%s)", "DW_OP_mod"); \ ++ c->last_error = c->error_buffer; \ ++ goto deref_fault; \ ++ } \ ++ a % b; \ ++}) ++ + /* PR 10601: user-space (user_regset) register access. */ + #if defined(STAPCONF_REGSET) + #include +diff --git a/runtime/unwind.c b/runtime/unwind.c +index 3e56965..810d9eb 100644 +--- a/runtime/unwind.c ++++ b/runtime/unwind.c +@@ -856,12 +856,26 @@ static int compute_expr(const u8 *expr, struct unwind_frame_info *frame, + BINOP(plus, +); + BINOP(minus, -); + BINOP(mul, *); +- BINOP(div, /); +- BINOP(mod, %); + BINOP(shl, <<); + BINOP(shra, >>); + #undef BINOP + ++ case DW_OP_mod: { ++ unsigned long b = POP; ++ unsigned long a = POP; ++ if (b == 0) ++ goto divzero; ++ PUSH (a % b); ++ } ++ ++ case DW_OP_div: { ++ long b = POP; ++ long a = POP; ++ if (b == 0) ++ goto divzero; ++ PUSH (a / b); ++ } ++ + case DW_OP_shr: { + unsigned long b = POP; + unsigned long a = POP; +@@ -944,6 +958,9 @@ overflow: + underflow: + _stp_warn("DWARF expression stack underflow in CFI\n"); + return 1; ++divzero: ++ _stp_warn("DWARF expression stack divide by zero in CFI\n"); ++ return 1; + + #undef NEED + #undef PUSH diff --git a/systemtap.spec b/systemtap.spec index 554bc5a..3aeba1f 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -16,7 +16,7 @@ Name: systemtap Version: 1.4 -Release: 5%{?dist} +Release: 6%{?dist} # for version, see also configure.ac Summary: Instrumentation System Group: Development/System @@ -59,6 +59,7 @@ BuildRequires: elfutils-devel >= %{elfutils_version} Patch2: sdt-regtable.patch Patch3: clonestopped.patch Patch4: gcc46warnings.patch +Patch5: bz702687.patch %if %{with_docs} BuildRequires: /usr/bin/latex /usr/bin/dvips /usr/bin/ps2pdf latex2html @@ -186,6 +187,7 @@ data from SystemTap instrumentation scripts. %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 %if %{with_bundled_elfutils} cd elfutils-%{elfutils_version} @@ -521,6 +523,9 @@ exit 0 %changelog +* Wed May 18 2011 Frank Ch. Eigler - 1.4-6 +- CVE-2011-1781, CVE-2011-1769 + * Sun Feb 13 2011 Dennis Gilmore - 1.4-5 - no crash on sparc