diff --git a/CVE-2012-0875.patch b/CVE-2012-0875.patch new file mode 100644 index 0000000..bc290be --- /dev/null +++ b/CVE-2012-0875.patch @@ -0,0 +1,87 @@ +commit 64b0cff3bee6b00cb4193ed887439c66055f85b4 +Author: Mark Wielaard +Date: Tue Feb 21 15:08:58 2012 +0100 + + PR13714 - Make sure REG_STATE.cfa_is_expr is always set correctly. + + runtime/unwind.c (processCFI): Always set REG_STATE.cfa_is_expr and + add new sanity checks to make sure the cfa definition rules are sane. + + Since the cfa expr pointer and cfa register/offset rule shared a union + not setting REG_STATE.cfa_is_expr could result in compute_expr () + wrongly being called and using the register/offset as expr pointer. + +diff --git a/runtime/unwind.c b/runtime/unwind.c +index c0fc9c2..e440177 100644 +--- a/runtime/unwind.c ++++ b/runtime/unwind.c +@@ -385,6 +385,7 @@ static void set_expr_rule(uleb128_t reg, enum item_location where, + uleb128_t len = get_uleb128(expr, end); + dbug_unwind(1, "reg=%lx, where=%d, expr=%lu@%p\n", + reg, where, len, *expr); ++ /* Sanity check that expr falls completely inside known data. */ + if (end - *expr >= len && reg < ARRAY_SIZE(REG_STATE.regs)) { + REG_STATE.regs[reg].where = where; + REG_STATE.regs[reg].expr = start; +@@ -524,30 +525,46 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, + case DW_CFA_def_cfa: + value = get_uleb128(&ptr.p8, end); + dbug_unwind(1, "map DW_CFA_def_cfa value %ld to reg_info idx %ld\n", value, DWARF_REG_MAP(value)); ++ REG_STATE.cfa_is_expr = 0; + REG_STATE.cfa.reg = value; + dbug_unwind(1, "DW_CFA_def_cfa reg=%ld\n", REG_STATE.cfa.reg); + /*nobreak */ + case DW_CFA_def_cfa_offset: +- REG_STATE.cfa.offs = get_uleb128(&ptr.p8, end); +- dbug_unwind(1, "DW_CFA_def_cfa_offset offs=%lx\n", REG_STATE.cfa.offs); ++ if (REG_STATE.cfa_is_expr != 0) { ++ _stp_warn("Unexpected DW_CFA_def_cfa_offset\n"); ++ } else { ++ REG_STATE.cfa.offs = get_uleb128(&ptr.p8, end); ++ dbug_unwind(1, "DW_CFA_def_cfa_offset offs=%lx\n", REG_STATE.cfa.offs); ++ } + break; + case DW_CFA_def_cfa_sf: + value = get_uleb128(&ptr.p8, end); + dbug_unwind(1, "map DW_CFA_def_cfa_sf value %ld to reg_info idx %ld\n", value, DWARF_REG_MAP(value)); ++ REG_STATE.cfa_is_expr = 0; + REG_STATE.cfa.reg = value; + /*nobreak */ + case DW_CFA_def_cfa_offset_sf: +- REG_STATE.cfa.offs = get_sleb128(&ptr.p8, end) * state->dataAlign; +- dbug_unwind(1, "DW_CFA_def_cfa_offset_sf offs=%lx\n", REG_STATE.cfa.offs); ++ if (REG_STATE.cfa_is_expr != 0) { ++ _stp_warn("Unexpected DW_CFA_def_cfa_offset_sf\n"); ++ } else { ++ REG_STATE.cfa.offs = get_sleb128(&ptr.p8, end) * state->dataAlign; ++ dbug_unwind(1, "DW_CFA_def_cfa_offset_sf offs=%lx\n", REG_STATE.cfa.offs); ++ } + break; + case DW_CFA_def_cfa_register: +- value = get_uleb128(&ptr.p8, end); +- dbug_unwind(1, "map DW_CFA_def_cfa_register value %ld to reg_info idx %ld\n", value, DWARF_REG_MAP(value)); +- REG_STATE.cfa.reg = value; ++ if (REG_STATE.cfa_is_expr != 0) { ++ _stp_warn("Unexpected DW_CFA_def_cfa_register\n"); ++ } else { ++ value = get_uleb128(&ptr.p8, end); ++ dbug_unwind(1, "map DW_CFA_def_cfa_register value %ld to reg_info idx %ld\n", value, DWARF_REG_MAP(value)); ++ REG_STATE.cfa.reg = value; ++ } + break; + case DW_CFA_def_cfa_expression: { + const u8 *cfa_expr = ptr.p8; + value = get_uleb128(&ptr.p8, end); ++ /* Sanity check that cfa_expr falls completely ++ inside known data. */ + if (ptr.p8 < end && end - ptr.p8 >= value) { + REG_STATE.cfa_is_expr = 1; + REG_STATE.cfa_expr = cfa_expr; +@@ -801,6 +818,7 @@ static int compute_expr(const u8 *expr, struct unwind_frame_info *frame, + { + /* + * We previously validated the length, so we won't read off the end. ++ * See sanity checks in set_expr() and for DW_CFA_def_cfa_expression. + */ + uleb128_t len = get_uleb128(&expr, (const u8 *) -1UL); + const u8 *const start = expr; diff --git a/systemtap.spec b/systemtap.spec index c4bcbd1..82b2b99 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -16,7 +16,7 @@ Name: systemtap Version: 1.7 -Release: 1%{?dist} +Release: 2%{?dist} # for version, see also configure.ac @@ -49,6 +49,8 @@ License: GPLv2+ URL: http://sourceware.org/systemtap/ Source: ftp://sourceware.org/pub/%{name}/releases/%{name}-%{version}.tar.gz +Patch10: CVE-2012-0875.patch + # Build* BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: gettext @@ -259,6 +261,8 @@ find . \( -name configure -o -name config.h.in \) -print | xargs touch cd .. %endif +%patch10 -p1 + %build %if %{with_bundled_elfutils} @@ -596,6 +600,9 @@ exit 0 # ------------------------------------------------------------------------ %changelog +* Wed Feb 22 2012 Frank Ch. Eigler - 1.7-2 +- CVE-2012-0875 (kernel panic when processing malformed DWARF unwind data) + * Wed Feb 01 2012 Frank Ch. Eigler - 1.7-1 - Upstream release. - Reorganize subpackages, new -client and -devel for subset installations.