From c888d4e1d889f7d89d652030ba75633c21bf94f559830ebde9f220bdc114fe71 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Tue, 8 Dec 2009 01:08:09 +0000 Subject: [PATCH 1/8] Accepting request 25952 from home:jones_tony:Factory Copy from home:jones_tony:Factory/systemtap via accept of submit request 25952 revision 3. Request was accepted with message: OBS-URL: https://build.opensuse.org/request/show/25952 OBS-URL: https://build.opensuse.org/package/show/devel:tools/systemtap?expand=0&rev=7 --- ready | 0 systemtap-1.0.tar.bz2 | 3 + systemtap-1.1.tar.bz2 | 3 - systemtap-CVE-2009-4273.diff | 925 ------------------ systemtap-CVE-2010-0411.diff | 187 ---- ...VE-limit-dwarf-expression-stack-size.patch | 135 +++ systemtap-CVE-limit-printf-arguments.patch | 75 ++ systemtap-CVE-unwind-table-size-checks.patch | 193 ++++ systemtap-docdir-fix.diff | 17 +- systemtap-docs.changes | 5 - systemtap-docs.spec | 23 +- systemtap-ioblock-suse-kernel-fix.diff | 12 +- systemtap-prevent-nested-arg.diff | 182 ---- systemtap-xmlto-fop.diff | 8 +- systemtap.changes | 13 - systemtap.spec | 101 +- 16 files changed, 473 insertions(+), 1409 deletions(-) create mode 100644 ready create mode 100644 systemtap-1.0.tar.bz2 delete mode 100644 systemtap-1.1.tar.bz2 delete mode 100644 systemtap-CVE-2009-4273.diff delete mode 100644 systemtap-CVE-2010-0411.diff create mode 100644 systemtap-CVE-limit-dwarf-expression-stack-size.patch create mode 100644 systemtap-CVE-limit-printf-arguments.patch create mode 100644 systemtap-CVE-unwind-table-size-checks.patch delete mode 100644 systemtap-prevent-nested-arg.diff diff --git a/ready b/ready new file mode 100644 index 0000000..473a0f4 diff --git a/systemtap-1.0.tar.bz2 b/systemtap-1.0.tar.bz2 new file mode 100644 index 0000000..54bc50d --- /dev/null +++ b/systemtap-1.0.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a942ba85d6360023e6f8503a8dd4c8493d16b17cb474cc8f0ad5a50cec3607a +size 1205746 diff --git a/systemtap-1.1.tar.bz2 b/systemtap-1.1.tar.bz2 deleted file mode 100644 index 073b472..0000000 --- a/systemtap-1.1.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1d620a9861cd7c9609fb8012faf20eafb632f3f3a919bf0c08bec3a14924e3a2 -size 1293846 diff --git a/systemtap-CVE-2009-4273.diff b/systemtap-CVE-2009-4273.diff deleted file mode 100644 index 005f70a..0000000 --- a/systemtap-CVE-2009-4273.diff +++ /dev/null @@ -1,925 +0,0 @@ -Subject: VUL-0: systemtap-server code exec -References: bnc#574243 -Signed-Off-By: Tony Jones - -Fix remaining portions of this CVE (part2) still present post release-1.1 -This second part is also referred to as CVE-2010-0412 - -Covers cases such as stap-client -B CC=/bin/rm CFLAGS=/ ... where the -execution is done by make - - - -commit b75067caf1bb416af21473e40c917d953531e9f9 -Author: Dave Brolley -Date: Mon Jan 18 11:56:13 2010 -0500 - - Correct client-side quoting issues discovered by fche during the server-side reimplementation. - - Also add the test cases to the test suite. - -commit 241443ad36a5a2cacb9e8e6f12f808d304835f2a -Author: Dave Brolley -Date: Tue Feb 2 08:26:01 2010 -0500 - - PR 11105: Remaining client-side problems: - - stap-client: Correct handling of embedded newlines in arguments. - server_args.exp: Add additional cases discovered by fche and by fuzzing. - -commit 4240be911e37b817727ecb33f321f0ea389ede61 -Author: Dave Brolley -Date: Mon Feb 15 15:01:28 2010 -0500 - - Don't pass client-only options to the server. - - Also correct parsing of the --server option. - -commit d2334a2233f4efd055dab021c603f7c046730a66 -Author: Dave Brolley -Date: Tue Feb 2 14:08:31 2010 -0500 - - Compile server logging and robustness. - - Log certificate location and status when starting server. - Additional care in handling arguments in stap-serverd. - New test case discovered by fuzzing added and fixed. - -commit c0d1b5a004b9949bb455b7dbe17b335b7cab9ead -Author: Frank Ch. Eigler -Date: Fri Feb 12 10:25:43 2010 -0500 - - PR11105 part 2: tighten constraints on stap-server parameters passed to make - - * util.h, util.cxx (assert_match_regexp): New function. - * main.cxx (main): Constrain -R, -r, -a, -D, -S, -q, -B flags. - * stap-serverd (listen): Harden stap-server-connect with ulimit/loop. - * testsuite/systemtap.server/{client,server}_args.exp: Revised. - -commit cc9e5488d82b728e568bca1f8d6094856fc8e641 -Author: Frank Ch. Eigler -Date: Fri Feb 12 10:39:58 2010 -0500 - - PR11105 part 2a, fix buggy \\. in -r option regexp - ---- - main.cxx | 24 ++-- - stap-client | 151 +++++++++++++++++------------ - stap-gen-cert | 43 ++++---- - stap-serverd | 40 +++++-- - testsuite/systemtap.server/client_args.exp | 28 ++--- - testsuite/systemtap.server/hello.stp | 2 - testsuite/systemtap.server/server_args.exp | 49 +++++---- - util.cxx | 36 ++++++ - util.h | 2 - 9 files changed, 238 insertions(+), 137 deletions(-) - ---- a/main.cxx -+++ b/main.cxx -@@ -57,7 +57,7 @@ version () - << "SystemTap translator/driver " - << "(version " << VERSION << "/" << dwfl_version (NULL) - << " " << GIT_MESSAGE << ")" << endl -- << "Copyright (C) 2005-2009 Red Hat, Inc. and others" << endl -+ << "Copyright (C) 2005-2010 Red Hat, Inc. and others" << endl - << "This is free software; see the source for copying conditions." << endl; - } - -@@ -670,12 +670,12 @@ main (int argc, char * const argv []) - break; - - case 'o': -+ // NB: client_options not a problem, since pass 1-4 does not use output_file. - s.output_file = string (optarg); - break; - - case 'R': -- if (client_options) -- client_options_disallowed += client_options_disallowed.empty () ? "-R" : ", -R"; -+ if (client_options) { cerr << "ERROR: -R invalid with --client-options" << endl; usage(s,1); } - s.runtime_path = string (optarg); - break; - -@@ -684,6 +684,7 @@ main (int argc, char * const argv []) - client_options_disallowed += client_options_disallowed.empty () ? "-m" : ", -m"; - s.module_name = string (optarg); - save_module = true; -+ // XXX: convert to assert_regexp_match() - { - string::size_type len = s.module_name.length(); - -@@ -728,15 +729,14 @@ main (int argc, char * const argv []) - break; - - case 'r': -- if (client_options) -- client_options_disallowed += client_options_disallowed.empty () ? "-r" : ", -r"; -+ if (client_options) // NB: no paths! -+ assert_regexp_match("-r parameter from client", optarg, "^[a-z0-9_.-]+$"); - setup_kernel_release(s, optarg); - break; - - case 'a': -- if (client_options) -- client_options_disallowed += client_options_disallowed.empty () ? "-a" : ", -a"; -- s.architecture = string(optarg); -+ assert_regexp_match("-a parameter", optarg, "^[a-z0-9_-]+$"); -+ s.architecture = string(optarg); - break; - - case 'k': -@@ -783,16 +783,19 @@ main (int argc, char * const argv []) - break; - - case 'D': -+ assert_regexp_match ("-D parameter", optarg, "^[a-z_][a-z_0-9]*(=[a-z_0-9]+)?$"); - if (client_options) - client_options_disallowed += client_options_disallowed.empty () ? "-D" : ", -D"; - s.macros.push_back (string (optarg)); - break; - - case 'S': -+ assert_regexp_match ("-S parameter", optarg, "^[0-9]+(,[0-9]+)?$"); - s.size_option = string (optarg); - break; - - case 'q': -+ if (client_options) { cerr << "ERROR: -q invalid with --client-options" << endl; usage(s,1); } - s.tapset_compile_coverage = true; - break; - -@@ -823,9 +826,8 @@ main (int argc, char * const argv []) - break; - - case 'B': -- if (client_options) -- client_options_disallowed += client_options_disallowed.empty () ? "-B" : ", -B"; -- s.kbuildflags.push_back (string (optarg)); -+ if (client_options) { cerr << "ERROR: -B invalid with --client-options" << endl; usage(s,1); } -+ s.kbuildflags.push_back (string (optarg)); - break; - - case 0: ---- a/stap-client -+++ b/stap-client -@@ -2,7 +2,7 @@ - - # Compile server client for systemtap - # --# Copyright (C) 2008, 2009, 2010 Red Hat Inc. -+# Copyright (C) 2008-2010 Red Hat Inc. - # - # This file is part of systemtap, and is free software. You can - # redistribute it and/or modify it under the terms of the GNU General -@@ -84,34 +84,34 @@ function parse_options { - # Each command line argument will be written to its own file within the - # request package. - argc=1 -+ packed_options='-' - arg_subst= - - while test $# != 0 - do - advance=0 - dash_seen=0 -+ client_arg=0 - - # Start of a new token. - first_token="$1" - until test $advance != 0 - do - # Identify the next option -- first_char=`expr "$first_token" : '\(.\).*'` -+ first_char="${first_token:0:1}" - second_char= - if test $dash_seen = 0; then - if test "$first_char" = "-"; then - if test "$first_token" != "-"; then - # It's not a lone dash, so it's an option. - # Is it a long option (i.e. --option)? -- second_char=`expr "$first_token" : '.\(.\).*'` -+ second_char="${first_token:1:1}" - if test "X$second_char" = "X-"; then -- long_option=`expr "$first_token" : '--\(.*\)=.*'` -- test "X$long_option" != "X" || long_option=`expr "$first_token" : '--\(.*\)'` -- case $long_option in -- ssl) -+ case "$first_token" in -+ --ssl=*) - process_ssl "$first_token" - ;; -- server) -+ --server=*) - process_server "$first_token" - ;; - *) -@@ -123,9 +123,9 @@ function parse_options { - fi - # It's not a lone dash, or a long option, so it's a short option string. - # Remove the dash. -- first_token=`expr "$first_token" : '-\(.*\)'` -+ first_token="${first_token:1}" - dash_seen=1 -- first_char=`expr "$first_token" : '\(.\).*'` -+ first_char="${first_token:0:1}" - fi - fi - if test $dash_seen = 0; then -@@ -145,69 +145,69 @@ function parse_options { - # We are at the start of an option. Look at the first character. - case $first_char in - a) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_a "$stap_arg" - ;; - B) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - c) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_c "$stap_arg" - ;; - D) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - e) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_e "$stap_arg" - ;; - I) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_I "$stap_arg" - ;; - k) - keep_temps=1 - ;; - l) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - p_phase=2 - ;; - L) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - p_phase=2 - ;; - m) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_m "$stap_arg" - ;; - o) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_o "$stap_arg" - ;; - p) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_p "$stap_arg" - ;; - r) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_r "$stap_arg" - ;; - R) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_R "$stap_arg" - ;; - s) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - S) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - v) - v_level=$(($v_level + 1)) - ;; - x) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - *) - # An unknown or unimportant flag. -@@ -216,7 +216,7 @@ function parse_options { - - if test $advance = 0; then - # Just another flag character. Consume it. -- first_token=`expr "$first_token" : '.\(.*\)'` -+ first_token="${first_token:1}" - if test "X$first_token" = "X"; then - advance=$(($advance + 1)) - fi -@@ -224,9 +224,19 @@ function parse_options { - done - - # Consume the arguments we just processed. -- while test $advance != 0 -- do -- # Place the argument is a numbered file within our temp -+ while test $advance != 0; do -+ # Does the final argument file contain a client-side file -+ # name which must be changed to a server-side name? -+ local arg -+ if test "X$arg_subst" != "X" -a $advance = 1; then -+ arg="$arg_subst" -+ arg_subst= -+ else -+ arg="$1" -+ fi -+ -+ # If it's not client-only argument, -+ # place the argument in a numbered file within our temp - # directory. - # o We don't write a newline at the end, since newline could be - # part of the argument. -@@ -234,20 +244,16 @@ function parse_options { - # in order to avoid having 'echo' interpret the output as - # its own option. We then remove the X. - # There must be a better way. -- echo -n "X$1" > "$tmpdir_client/argv$argc" -- sed -i "s|^X||" "$tmpdir_client/argv$argc" -- -- # Does the final argument file contain client-side data -- # which must be changed to server-side data? -- if test "X$arg_subst" != "X" -a $advance = 1; then -- sed -i "s|$stap_arg|$arg_subst|" "$tmpdir_client/argv$argc" -- arg_subst= -+ if test $client_arg = 0; then -+ echo -n "X$arg" > "$tmpdir_client/argv$argc" -+ sed -i "s|^X||" "$tmpdir_client/argv$argc" -+ argc=$(($argc + 1)) - fi - - # Get the next argument. - shift -- argc=$(($argc + 1)) - advance=$(($advance - 1)) -+ packed_options='-' - done - done - -@@ -256,7 +262,8 @@ function parse_options { - if test "X$script_file" != "X"; then - local local_name - if test "$script_file" != "-"; then -- local_name=`generate_client_temp_name "$script_file"` -+ generate_client_temp_name "$script_file" -+ local_name="$client_temp_name" - else - local_name="-" - fi -@@ -277,8 +284,9 @@ function parse_options { - # Collect an argument to the given option - function get_arg { - # Remove first character. -- local opt=`expr "$1" : '\(.\).*'` -- local first=`expr "$1" : '.\(.*\)'` -+ local opt="${1:0:1}" -+ local first="${1:1}" -+ packed_options="${packed_options}$opt" - - # Advance to the next token, if the first one is exhausted. - if test "X$first" = "X"; then -@@ -294,7 +302,8 @@ function get_arg { - # - # Process the --ssl option. - function process_ssl { -- local db=`expr "$1" : '--ssl=\(.*\)'` -+ client_arg=1 -+ local db="${1:6}" - - test "X$db" != "X" || \ - fatal "Missing argument to --ssl" -@@ -308,7 +317,8 @@ function process_ssl { - # - # Process the --server option. - function process_server { -- local spec=`expr "$1" : '--server=\(.*\)'` -+ client_arg=1 -+ local spec="${1:9}" - - test "X$spec" != "X" || \ - fatal "Missing argument to --server" -@@ -335,12 +345,19 @@ function process_e { - fi - } - --# function: process_I ARGUMENT -+# function: process_I ARGUMENT ORIGINAL_ARGUMENT - # - # Process the -I flag. - function process_I { - test "X$1" = "X" && return -- arg_subst=tapsets/`include_file_or_directory tapsets "$1"` -+ test "${1:0:1}" = " -+" && return -+ include_file_or_directory tapsets "$1" -+ if test $advance = 1; then -+ arg_subst="${packed_options}tapsets/$included_name" -+ else -+ arg_subst="tapsets/$included_name" -+ fi - } - - # function: process_m ARGUMENT -@@ -369,7 +386,7 @@ function process_p { - # - # Process the -r flag. - function process_r { -- local first_char=`expr "$1" : '\(.\).*'` -+ local first_char="${1:0:1}" - - if test "$first_char" = "/"; then # fully specified path - kernel_build_tree="$1" -@@ -402,23 +419,34 @@ function process_a { - fi - } - --# function: process_R ARGUMENT -+# function: process_R ARGUMENT ORIGINAL_ARGUMENT - # - # Process the -R flag. - function process_R { - test "X$1" = "X" && return -- arg_subst=runtime/`include_file_or_directory runtime "$1"` -+ test "${1:0:1}" = " -+" && return -+ include_file_or_directory runtime "$1" -+ if test $advance = 1; then -+ arg_subst="${packed_options}runtime/$included_name" -+ else -+ arg_subst="runtime/$included_name" -+ fi - } - - # function: include_file_or_directory PREFIX NAME - # - # Include the given file or directory in the client's temporary --# tree to be sent to the server. -+# tree to be sent to the server and save it's name in the variable -+# included_name. We use a global variable instread of echoing the -+# result since the use of `include_file_or_directory` loses a trailing -+# newline. - function include_file_or_directory { - # Add a symbolic link of the named file or directory to our temporary - # directory, but only if the file or directory exists. -- local local_name=`generate_client_temp_name "$2"` -- echo "$local_name" -+ generate_client_temp_name "$2" -+ local local_name="$client_temp_name" -+ included_name="$local_name" - test -e "/$local_name" || return - - local local_dirname=`dirname "$local_name"` -@@ -431,15 +459,20 @@ function include_file_or_directory { - # function: generate_client_temp_name NAME - # - # Generate the name to be used for the given file/directory relative to the --# client's temporary directory. -+# client's temporary directory and stores it in the variable -+# client_temp_name. We use a global variable instread of echoing the -+# result since the use of `generate_client_temp_name` loses a trailing -+# newline. - function generate_client_temp_name { - # Transform the name into a fully qualified path name -- local full_name=`echo "X$1" | sed "s,^X\\\([^/]\\\),$wd/\\\\1," | sed 's,^X,,'` -+ local full_name="$1" -+ test "${full_name:0:1}" != "/" && full_name="$wd/$full_name" - - # The same name without the initial / or trailing / -- local local_name=`echo "$full_name" | sed 's,^/\(.*\),\1,'` -- local_name=`echo "$local_name" | sed 's,\(.*\)/$,\1,'` -- echo "$local_name" -+ local local_name="${full_name:1}" -+ test "${local_name: -1:1}" = "/" && local_name="${local_name:0:$((${#local_name}-1))}" -+ -+ client_temp_name="$local_name" - } - - # function: create_request -@@ -456,7 +489,7 @@ function create_request { - fatal "Cannot create temporary directory " $tmpdir_client/script - cat > "$tmpdir_client/script/$script_file" - else -- include_file_or_directory script "$script_file" > /dev/null -+ include_file_or_directory script "$script_file" - fi - fi - -@@ -505,7 +538,7 @@ function unpack_response { - # 2) a file called stderr - # 3) a file called rc - # 4) optionally a directory named to match stap?????? -- num_files=`ls $tmpdir_server | wc -l` -+ local num_files=`ls $tmpdir_server | wc -l` - test $num_files = 4 -o $num_files = 3 || \ - fatal "Wrong number of files in server's temp directory" - test -f $tmpdir_server/stdout || \ ---- a/stap-gen-cert -+++ b/stap-gen-cert -@@ -3,7 +3,7 @@ - # Generate a certificate for the systemtap server and add it to the - # database of trusted servers for the client. - # --# Copyright (C) 2008, 2009 Red Hat Inc. -+# Copyright (C) 2008-2010 Red Hat Inc. - # - # This file is part of systemtap, and is free software. You can - # redistribute it and/or modify it under the terms of the GNU General -@@ -14,61 +14,68 @@ - . ${PKGLIBEXECDIR}stap-env - - # Obtain the certificate database directory name. --serverdb=$1 -+serverdb="$1" - if test "X$serverdb" = "X"; then -- serverdb=$stap_ssl_db/server -+ serverdb="$stap_ssl_db/server" - fi --rm -fr $serverdb -+rm -fr "$serverdb" - - # Create the server's certificate database directory. --if ! mkdir -p -m 755 $serverdb; then -+if ! mkdir -p -m 755 "$serverdb"; then - echo "Unable to create the server certificate database directory: $serverdb" >&2 - exit 1 - fi - - # Create the certificate database password file. Care must be taken - # that this file is only readable by the owner. --if ! (touch $serverdb/pw && chmod 600 $serverdb/pw); then -+if ! (touch "$serverdb/pw" && chmod 600 "$serverdb/pw"); then - echo "Unable to create the server certificate database password file: $serverdb/pw" >&2 - exit 1 - fi - - # Generate a random password. --mkpasswd -l 20 > $serverdb/pw 2>/dev/null || \ --apg -a 1 -n 1 -m 20 -x 20 > $serverdb/pw 2>/dev/null || \ --(read -n20 password $serverdb/pw) -+mkpasswd -l 20 > "$serverdb/pw" 2>/dev/null || \ -+apg -a 1 -n 1 -m 20 -x 20 > "$serverdb/pw" 2>/dev/null || \ -+(read -n20 password "$serverdb/pw") - - # Generate the server certificate database --if ! certutil -N -d $serverdb -f $serverdb/pw > /dev/null; then -+if ! certutil -N -d "$serverdb" -f "$serverdb/pw" > /dev/null; then - echo "Unable to initialize the server certificate database directory: $serverdb" >&2 - exit 1 - fi - - # We need some random noise for generating keys --dd bs=123 count=1 < /dev/urandom > $serverdb/noise 2> /dev/null -+dd bs=123 count=1 < /dev/urandom > "$serverdb/noise" 2> /dev/null - - # Generate a request for the server's certificate. --certutil -R -d $serverdb -f $serverdb/pw -s "CN=Systemtap Compile Server, OU=Systemtap, O=Red Hat, C=US" -o $serverdb/stap.req -z $serverdb/noise 2> /dev/null --rm -fr $serverdb/noise -+certutil -R -d "$serverdb" -f "$serverdb/pw" -s "CN=Systemtap Compile Server, OU=Systemtap, O=Red Hat, C=US" \ -+ -o "$serverdb/stap.req" -z "$serverdb/noise" 2> /dev/null -+rm -fr "$serverdb/noise" - - # Create the certificate file first so that it always has the proper access permissions. --if ! (touch $serverdb/$stap_certfile && chmod 644 $serverdb/$stap_certfile); then -+if ! (touch "$serverdb/$stap_certfile" && chmod 644 "$serverdb/$stap_certfile"); then - echo "Unable to create the server certificate file: $serverdb/$stap_certfile" >&2 - exit 1 - fi - --# Now generate the actual certificate. --certutil -C -i $serverdb/stap.req -o $serverdb/$stap_certfile -x -d $serverdb -f $serverdb/pw -5 -8 "$HOSTNAME,localhost" >/dev/null <<-EOF -+# Now generate the actual certificate. Make is valid for 1 year. -+certutil -C -i "$serverdb/stap.req" -o "$serverdb/$stap_certfile" -x -d "$serverdb" \ -+ -f "$serverdb/pw" -v 12 -5 -8 "$HOSTNAME,localhost" >/dev/null <<-EOF - 1 - 3 - 7 - 8 - y - EOF --rm -fr $serverdb/stap.req -+rm -fr "$serverdb/stap.req" - - # Add the certificate to the server's certificate/key database as a trusted peer, ssl server and object signer --certutil -A -n stap-server -t "PCu,,PCu" -i $serverdb/$stap_certfile -d $serverdb -f $serverdb/pw -+certutil -A -n stap-server -t "PCu,,PCu" -i "$serverdb/$stap_certfile" -d "$serverdb" -f "$serverdb/pw" - -+# Print some information about the certificate. - echo "Certificate $serverdb/$stap_certfile created and added to database $serverdb" -+certutil -L -d "$serverdb" -n stap-server | \ -+ awk '/Validity|Not After|Not Before/ { print $0 }' | \ -+ sed 's/^ */ /' -+ - exit 0 ---- a/stap-serverd -+++ b/stap-serverd -@@ -70,12 +70,18 @@ function initialization { - -x `which ${stap_exec_prefix}stap-client 2>/dev/null`; then - ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 - fi -- elif ! test -f $stap_ssl_db/client/cert8.db; then -- # If the client's database does not exist, then initialize it with our certificate. -- # Do this only if the client has been installed. -- if test -f `which ${stap_exec_prefix}stap-client` -a \ -- -x `which ${stap_exec_prefix}stap-client`; then -- ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 -+ else -+ echo "Certificate found in database $ssl_db" >> $logfile -+ certutil -L -d "$ssl_db" -n stap-server | \ -+ awk '/Validity|Not After|Not Before/ { print $0 }' | \ -+ sed 's/^ */ /' >> $logfile -+ if ! test -f $stap_ssl_db/client/cert8.db; then -+ # If the client's database does not exist, then initialize it with our certificate. -+ # Do this only if the client has been installed. -+ if test -f `which ${stap_exec_prefix}stap-client 2>/dev/null` -a \ -+ -x `which ${stap_exec_prefix}stap-client 2>/dev/null`; then -+ ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 -+ fi - fi - fi - fi -@@ -343,11 +349,19 @@ function advertise_presence { - function listen { - # The stap-server-connect program will listen forever - # accepting requests. -- ${stap_pkglibexecdir}stap-server-connect \ -- -p $port -n $nss_cert -d $ssl_db -w $nss_pw \ -- -s "$stap_options" \ -- >> $logfile 2>&1 & -- wait '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 -+ # CVE-2009-4273 ... or at least, until resource limits fire -+ while true; do # NB: loop to avoid DoS by deliberate rlimit-induced halt -+ # NB: impose resource limits in case of mischevious data inducing -+ # too much / long computation -+ (ulimit -f 50000 -s 1000 -t 60 -u 20 -v 500000; -+ exec ${stap_pkglibexecdir}stap-server-connect \ -+ -p $port -n $nss_cert -d $ssl_db -w $nss_pw \ -+ -s "$stap_options") & -+ stap_server_connect_pid=$! -+ wait -+ # NB: avoid superfast spinning in case of a ulimit or other failure -+ sleep 1 -+ done >> $logfile 2>&1 - } - - # function: warning [ MESSAGE ] -@@ -379,8 +393,8 @@ function terminate { - wait '%avahi-publish-service' >> $logfile 2>&1 - - # Kill any running 'stap-server-connect' job. -- kill -s SIGTERM '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 -- wait '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 -+ kill -s SIGTERM $stap_server_connect_pid >> $logfile 2>&1 -+ wait $stap_server_connect_pid >> $logfile 2>&1 - - exit - } ---- a/testsuite/systemtap.server/client_args.exp -+++ b/testsuite/systemtap.server/client_args.exp -@@ -5,33 +5,34 @@ set test "Invalid Server Client Argument - set test_file $srcdir/systemtap.server/test.stp - - # Test invalid combinations. --set error_regexp ".*You can't specify .* when --unprivileged is specified.*" -+set error_regexp ".*(ERROR)|(You can't specify .* when --unprivileged is specified).*" - - set invalid_options [list \ -- "--unprivileged --client-options -a i386" \ - "--unprivileged --client-options -B X=Y" \ - "--unprivileged --client-options -D X=Y" \ - "--unprivileged --client-options -I /tmp" \ - "--unprivileged --client-options -m test" \ - "--unprivileged --client-options -R /tmp" \ -- "--unprivileged --client-options -r [exec uname -r]" \ -- "--unprivileged --client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ -- "--client-options --unprivileged -a i386" \ -+ "--unprivileged --client-options -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ - "--client-options --unprivileged -B X=Y" \ - "--client-options --unprivileged -D X=Y" \ - "--client-options --unprivileged -I /tmp" \ - "--client-options --unprivileged -m test" \ - "--client-options --unprivileged -R /tmp" \ -- "--client-options --unprivileged -r [exec uname -r]" \ -- "--client-options --unprivileged -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ -- "--client-options -a i386 --unprivileged" \ -+ "--client-options --unprivileged -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ - "--client-options -B X=Y --unprivileged" \ - "--client-options -D X=Y --unprivileged" \ - "--client-options -I /tmp --unprivileged" \ - "--client-options -m test --unprivileged" \ - "--client-options -R /tmp --unprivileged" \ -- "--client-options -r [exec uname -r] --unprivileged" \ -- "--client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r] --unprivileged" \ -+ "--client-options -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r] --unprivileged" \ -+ "--client-options -R /path" \ -+ "-D \"foo;bar\"" \ -+ "-D 2=4" \ -+ "-D \"foo;bar\"" \ -+ "--client-options -r /path" \ -+ "-S /path" \ -+ "--client-options -q" \ - ] - - foreach options $invalid_options { -@@ -66,9 +67,8 @@ set valid_options [list \ - "-D X=Y" \ - "-I /tmp" \ - "-m test" \ -- "-R /tmp" \ - "-r [exec uname -r]" \ -- "-a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ -+ "-a i386 -B X=Y -D X=Y -I /tmp -m test -r [exec uname -r]" \ - "--unprivileged" \ - "--unprivileged -a i386" \ - "--unprivileged -B X=Y" \ -@@ -80,13 +80,11 @@ set valid_options [list \ - "--unprivileged -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ - "--client-options" \ - "--client-options -a i386" \ -- "--client-options -B X=Y" \ - "--client-options -D X=Y" \ - "--client-options -I /tmp" \ - "--client-options -m test" \ -- "--client-options -R /tmp" \ - "--client-options -r [exec uname -r]" \ -- "--client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ -+ "--client-options -a i386 -D X=Y -I /tmp -m test -r [exec uname -r]" \ - "--unprivileged --client-options" \ - "--client-options --unprivileged" \ - "--unprivileged -a i386 --client-options" \ ---- a/testsuite/systemtap.server/hello.stp -+++ b/testsuite/systemtap.server/hello.stp -@@ -1,4 +1,4 @@ --#! stap -+#! stap -p5 - - probe begin - { ---- a/testsuite/systemtap.server/server_args.exp -+++ b/testsuite/systemtap.server/server_args.exp -@@ -40,11 +40,13 @@ proc stap_direct_and_with_client {stap s - # Some messages contain the names of files or directories - # and will be prefixed for the client. - if {[regexp "^ (.*)" $expected_line match data]} { -- if {[regexp "^ tapsets/.*/$data" $line]} { -+ # Special characters in the regexp need to be quoted. -+ regsub -all "\[\"\\\\;\*\]" $data {\\\0} data -+ if {[regexp "^ tapsets.*/$data" $line]} { - incr n - continue - } -- if {[regexp "^ runtime/.*/$data" $line]} { -+ if {[regexp "^ runtime.*/$data" $line]} { - incr n - continue - } -@@ -57,7 +59,9 @@ proc stap_direct_and_with_client {stap s - } - } else { - if {[regexp "^Input file '(.*)' is empty or missing." $expected_line match data]} { -- if {[regexp "^Input file 'script/.*/$data' is empty or missing." $line]} { -+ # Special characters in the regexp need to be quoted. -+ regsub -all "\[\"\\\\;\*\]" $data {\\\0} data -+ if {[regexp "^Input file 'script.*/$data' is empty or missing." $line]} { - incr n - continue - } -@@ -110,21 +114,27 @@ if {[installtest_p]} then { - # for debugging a currently failing case and helps to ensure that previously - # fixed cases do not regress. - set previously_fixed [list \ -+ "-p1 -I=\\w94\nbh -e -Dhfuo0iu7 -c" \ -+ "-p1 -I8o\\2ie -e'1\\ -D\n\" -c" \ -+ "-p1 -Ira\\3;c g -e0fle'qq -Dr/316k\\o8 -cjyoc\n3" \ -+ "-p1 -I6p3 -elc -Dqgsgv' -c" \ -+ "-p1 -I\"vyv;z -ej\"/3 -D/ 01qck\n -c3u55zut" \ -+ "-p1 -I1 -eo9e\nx047q -D9xyefk0a -cvl98/x1'i" \ - "-p1 -c; test.stp" \ -- "-p1 -I4hgy96 -R -e5oo39p -Bile\\vp -Ddx8v -c4;" \ -- "-p1 -I -Repwd9 -esq3wors -Btmk;\\t -Dz -c*eibz8h2e" \ -- "-p1 -I -Ry a -em339db5 -B;ae41428d -Du2;c0ps -ch9o\\" \ -- "-p1 -Ipfjps4 -Rx479 -ebug4dc -Bih;fe2 -Du8vd fvkl -c" \ -- "-p1 -I0\"nspzjyf -R -e5r3up8h -Bgqnyjq6w -Dmi;ojp9m -cx;a2fat" \ -- "-p1 -Iu -R9 -ek7;r -Big -Dcu\"; -c\"hc" \ -- "-p1 -Icd4fidq -Rkj m40mv -edn -B7ria -D;8ha\\cjr -c1*vnq" \ -- "-p1 -I;3 -R3lq;vp -er8e -Bgdqjqdy -D -cb6k29z" \ -- "-p1 -Ircj -R -e -B -D -c\\vmww" \ -- "-p1 -Illc5 -Rug*\\o -e65wof9 -B qr*=x7x5 -D -cgx;" \ -- "-p1 -Iyaj420=3 -R -e\" -Bx68j -D -cd'5mi" \ -- "-p1 -Ir -Rwd8;;sjl -e -Bxh; -D29\\ -cj2szt;4" \ -- "-p1 -Ibno3=b4sk -R*5 -e' -Byl63flos -Dg2-j;e -c2ijx'" \ -- "-p1 -I285v7pl -R9a -eo5\\0 -Bfs* -D86s -c-c*v" \ -+ "-p1 -I4hgy96 -e5oo39p -Ddx8v -c4;" \ -+ "-p1 -I -esq3wors -Dz -c*eibz8h2e" \ -+ "-p1 -I a -em339db5 -Du2;c0ps -ch9o\\" \ -+ "-p1 -Ipfjps4 -ebug4dc -Du8vd fvkl -c" \ -+ "-p1 -I0\"nspzjyf -e5r3up8h -Dmi;ojp9m -cx;a2fat" \ -+ "-p1 -Iu -ek7;r -Dcu\"; -c\"hc" \ -+ "-p1 -Icd4fidq m40mv -edn -D;8ha\\cjr -c1*vnq" \ -+ "-p1 -I;3 -er8e -D -cb6k29z" \ -+ "-p1 -Ircj -e -D -c\\vmww" \ -+ "-p1 -Illc5 -e65wof9 qr*=x7x5 -D -cgx;" \ -+ "-p1 -Iyaj420=3 -e\" -D -cd'5mi" \ -+ "-p1 -Ir -e -D29\\ -cj2szt;4" \ -+ "-p1 -Ibno3=b4sk -e' -Dg2-j;e -c2ijx'" \ -+ "-p1 -I285v7pl -eo5\\0 -D86s -c-c*v" \ - ] - - set i 0 -@@ -140,7 +150,10 @@ foreach options $previously_fixed { - # Generate semi-random arguments containing with potential problem characters. - # Check that running systemtap with the client/server generates output - # comparable to running stap directly. --set dangerous_options [list "-I" "-R" "-e" "-B" "-D" "-c"] -+set dangerous_options [list "-I" "-e" "-D" "-c" "-S"] -+# NB: Other options could be candidates here, like -r and -B, but -+# there stap-server imposes more restrictions than local stap, so -+# this simple error-matching test cannot use them. - set argchars "0123456789/;*'=-\\\"\n abcdefghijklmnopqrstuvwxyz" - - for {set i 0} {$i < $iterations} {incr i} { ---- a/util.cxx -+++ b/util.cxx -@@ -1,5 +1,5 @@ - // Copyright (C) Andrew Tridgell 2002 (original file) --// Copyright (C) 2006, 2009 Red Hat Inc. (systemtap changes) -+// Copyright (C) 2006-2010 Red Hat Inc. (systemtap changes) - // - // This program is free software; you can redistribute it and/or - // modify it under the terms of the GNU General Public License as -@@ -19,6 +19,8 @@ - #include "sys/sdt.h" - #include - #include -+#include -+#include - - extern "C" { - #include -@@ -31,6 +33,7 @@ extern "C" { - #include - #include - #include -+#include - } - - using namespace std; -@@ -413,4 +416,35 @@ kill_stap_spawn(int sig) - return spawned_pid ? kill(spawned_pid, sig) : 0; - } - -+ -+void assert_regexp_match (const string& name, const string& value, const string& re) -+{ -+ typedef map cache; -+ static cache compiled; -+ cache::iterator it = compiled.find (re); -+ regex_t* r = 0; -+ if (it == compiled.end()) -+ { -+ r = new regex_t; -+ int rc = regcomp (r, re.c_str(), REG_ICASE|REG_NOSUB|REG_EXTENDED); -+ if (rc) { -+ cerr << "regcomp " << re << " (" << name << ") error rc=" << rc << endl; -+ exit(1); -+ } -+ compiled[re] = r; -+ } -+ else -+ r = it->second; -+ -+ // run regexec -+ int rc = regexec (r, value.c_str(), 0, 0, 0); -+ if (rc) -+ { -+ cerr << "ERROR: Safety pattern mismatch for " << name -+ << " ('" << value << "' vs. '" << re << "') rc=" << rc << endl; -+ exit(1); -+ } -+} -+ -+ - /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ ---- a/util.h -+++ b/util.h -@@ -21,7 +21,7 @@ const std::string cmdstr_quoted(const st - std::string git_revision(const std::string& path); - int stap_system(int verbose, const std::string& command); - int kill_stap_spawn(int sig); -- -+void assert_regexp_match (const std::string& name, const std::string& value, const std::string& re); - - // stringification generics - diff --git a/systemtap-CVE-2010-0411.diff b/systemtap-CVE-2010-0411.diff deleted file mode 100644 index 59cf89a..0000000 --- a/systemtap-CVE-2010-0411.diff +++ /dev/null @@ -1,187 +0,0 @@ -Subject: VUL-1: systemtap: DoS issue in __get_argv() function -References: bnc#577382 -Signed-Off-By: Tony Jones - -commit a2d399c87a642190f08ede63dc6fc434a5a8363a -Author: Josh Stone -Date: Thu Feb 4 17:47:31 2010 -0800 - - PR11234: Rewrite __get_argv without embedded-C - - We now implement __get_argv's string building in pure stap script. - Also, every argument is now quoted, which is different than before, but - it's much more robust about handling special characters. - -diff --git a/tapset/aux_syscalls.stp b/tapset/aux_syscalls.stp -index bab0f64..e762b37 100644 ---- a/tapset/aux_syscalls.stp -+++ b/tapset/aux_syscalls.stp -@@ -399,124 +399,53 @@ function __sem_flags:string(semflg:long) - - - /* This function copies an argv from userspace. */ --function __get_argv:string(a:long, first:long) --%{ /* pure */ -- char __user *__user *argv = (char __user *__user *)(long)THIS->a; -- char __user *vstr; -- int space, rc, len = MAXSTRINGLEN; -- char *str = THIS->__retvalue; -- char buf[80]; -- char *ptr = buf; -- -- -- if (THIS->first && argv) -- argv++; -- -- while (argv != NULL) { -- if (__stp_get_user (vstr, argv)) -- break; -- -- if (vstr == NULL) -- break; -- -- rc = _stp_strncpy_from_user(buf, vstr, 79); -- if (rc <= 0) -- break; -- -- /* check for whitespace in string */ -- buf[rc] = 0; -- ptr = buf; -- space = 0; -- while (*ptr && rc--) { -- if (isspace(*ptr++)) { -- space = 1; -- break; -- } -- } -- -- if (len != MAXSTRINGLEN && len) { -- *str++=' '; -- len--; -- } -- -- if (space && len) { -- *str++='\"'; -- len--; -- } -- -- rc = strlcpy (str, buf, len); -- str += rc; -- len -= rc; -- -- if (space && len) { -- *str++='\"'; -- len--; -- } -- -- argv++; -+function __get_argv:string(argv:long, first:long) -+{ -+%( CONFIG_64BIT == "y" %? -+ if (first && argv) -+ argv += 8 -+ while (argv) { -+ vstr = user_long(argv) -+ if (!vstr) -+ break -+ if (len) -+ str .= " " -+ str .= user_string_quoted(vstr) -+ -+ newlen = strlen(str) -+ if (newlen == len) -+ break -+ len = newlen -+ argv += 8 - } -- *str = 0; --%} --/* This function copies an argv from userspace. */ --function __get_compat_argv:string(a:long, first:long) --%{ /* pure */ --#ifdef CONFIG_COMPAT -- compat_uptr_t __user *__user *argv = (compat_uptr_t __user *__user *)(long)THIS->a; -- compat_uptr_t __user *vstr; -- int space, rc, len = MAXSTRINGLEN; -- char *str = THIS->__retvalue; -- char buf[80]; -- char *ptr = buf; -- -- if (THIS->first && argv) -- argv++; -- -- while (argv != NULL) { -- if (__stp_get_user (vstr, argv)) -- break; -- -- if (vstr == NULL) -- break; -- -- rc = _stp_strncpy_from_user(buf, (char *)vstr, 79); -- if (rc <= 0) -- break; -- -- /* check for whitespace in string */ -- buf[rc] = 0; -- ptr = buf; -- space = 0; -- while (*ptr && rc--) { -- if (isspace(*ptr++)) { -- space = 1; -- break; -- } -- } -- -- if (len != MAXSTRINGLEN && len) { -- *str++=' '; -- len--; -- } -- -- if (space && len) { -- *str++='\"'; -- len--; -- } -- -- rc = strlcpy (str, buf, len); -- str += rc; -- len -= rc; -- -- if (space && len) { -- *str++='\"'; -- len--; -- } - -- argv++; -+ return str -+%: -+ return __get_compat_argv(argv, first) -+%) -+} -+/* This function copies an argv from userspace. */ -+function __get_compat_argv:string(argv:long, first:long) -+{ -+ if (first && argv) -+ argv += 4 -+ while (argv) { -+ vstr = user_int(argv) & 0xffffffff -+ if (!vstr) -+ break -+ if (len) -+ str .= " " -+ str .= user_string_quoted(vstr) -+ -+ newlen = strlen(str) -+ if (newlen == len) -+ break -+ len = newlen -+ argv += 4 - } -- *str = 0; --#endif --%} -+ -+ return str -+} - - /* - * Return the symbolic string representation diff --git a/systemtap-CVE-limit-dwarf-expression-stack-size.patch b/systemtap-CVE-limit-dwarf-expression-stack-size.patch new file mode 100644 index 0000000..4394e4f --- /dev/null +++ b/systemtap-CVE-limit-dwarf-expression-stack-size.patch @@ -0,0 +1,135 @@ +From: Jan Lieskovsky +Subject: Three SystemTap-1.0 denial of service issues +References: CVE-2009-2911, BNC#548361 +Upstream: yes + + Three denial of service flaws were found in the SystemTap +instrumentation system of version 1.0, when the --unprivileged mode was +activated: + +b, Kernel stack frame overflow allows local attackers to cause denial +of service via specially-crafted user-provided DWARF information. + +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/systemtap-CVE-limit-printf-arguments.patch b/systemtap-CVE-limit-printf-arguments.patch new file mode 100644 index 0000000..32041a0 --- /dev/null +++ b/systemtap-CVE-limit-printf-arguments.patch @@ -0,0 +1,75 @@ +From: Jan Lieskovsky +Subject: Three SystemTap-1.0 denial of service issues +References: CVE-2009-2911, BNC#548361 +Upstream: yes + + Three denial of service flaws were found in the SystemTap +instrumentation system of version 1.0, when the --unprivileged mode was +activated: + +a, Kernel stack overflow allows local attackers to cause denial of service or +execute arbitrary code via long number of parameters, provided to the print* +call. + +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 tmp; + + diff --git a/systemtap-CVE-unwind-table-size-checks.patch b/systemtap-CVE-unwind-table-size-checks.patch new file mode 100644 index 0000000..408239b --- /dev/null +++ b/systemtap-CVE-unwind-table-size-checks.patch @@ -0,0 +1,193 @@ +From: Jan Lieskovsky +Subject: Three SystemTap-1.0 denial of service issues +References: CVE-2009-2911, BNC#548361 +Upstream: yes + + Three denial of service flaws were found in the SystemTap +instrumentation system of version 1.0, when the --unprivileged mode was +activated: + +c, Absent check(s) for the upper bound of the size of the unwind table + and for the upper bound of the size of each of the CIE/CFI records, could + allow an attacker to cause a denial of service (infinite loop). + +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 != ¬_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 == ¬_fde || (ptrType = fde_pointer_type(cie)) < 0) ++ if (cie == NULL || cie == ¬_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 + } + ++// 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/systemtap-docdir-fix.diff b/systemtap-docdir-fix.diff index ecdced0..9cb4ad9 100644 --- a/systemtap-docdir-fix.diff +++ b/systemtap-docdir-fix.diff @@ -1,10 +1,3 @@ -From: Tony Jones -Subject: change doc install path -References: none -Upstream: never - -SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. - --- Makefile.am | 2 +- doc/Makefile.am | 2 +- @@ -14,15 +7,15 @@ SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. --- a/Makefile.am +++ b/Makefile.am -@@ -257,7 +257,7 @@ install-data-local: +@@ -218,7 +218,7 @@ | while read f; do if test -x $$f; then \ i_cmd="$(INSTALL_PROGRAM)"; else \ i_cmd="$(INSTALL_DATA)"; fi; \ - $$i_cmd -D $$f $(DESTDIR)$(docdir)/examples/$$f; done) + $$i_cmd -D $$f $(DESTDIR)$(datadir)/doc/packages/systemtap/examples/$$f; done) test -e $(DESTDIR)$(sysconfdir)/systemtap || mkdir -p $(DESTDIR)$(sysconfdir)/systemtap - if BUILD_SERVER - test -e $(DESTDIR)$(localstatedir)/run/stap-server || mkdir -p $(DESTDIR)$(localstatedir)/run/stap-server + + TEST_COV_DIR = coverage --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -2,7 +2,7 @@ @@ -31,7 +24,7 @@ SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. PDF_FILES = tutorial.pdf langref.pdf -DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap +DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/packages/systemtap - SUBDIRS = SystemTap_Tapset_Reference beginners + SUBDIRS = SystemTap_Tapset_Reference if BUILD_DOCS --- a/doc/SystemTap_Tapset_Reference/Makefile.am @@ -50,7 +43,7 @@ SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. ### --- a/stapex.3stap.in +++ b/stapex.3stap.in -@@ -114,12 +114,12 @@ To list the probeable functions and loca +@@ -114,12 +114,12 @@ .SH MORE EXAMPLES Larger examples, demos and samples can be found in diff --git a/systemtap-docs.changes b/systemtap-docs.changes index 1a076e3..8573048 100644 --- a/systemtap-docs.changes +++ b/systemtap-docs.changes @@ -1,8 +1,3 @@ -------------------------------------------------------------------- -Thu Mar 11 22:49:52 UTC 2010 - tonyj@novell.com - -- Update to version 1.1. See systemtap.changes for full changelog. - ------------------------------------------------------------------- Wed Dec 2 23:52:10 UTC 2009 - tonyj@novell.com diff --git a/systemtap-docs.spec b/systemtap-docs.spec index 61dd589..f29e359 100644 --- a/systemtap-docs.spec +++ b/systemtap-docs.spec @@ -1,7 +1,7 @@ # -# spec file for package systemtap-docs (Version 1.1) +# spec file for package systemtap-docs (Version 0.9.9) # -# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -22,11 +22,13 @@ Name: systemtap-docs BuildRequires: gcc-c++ libebl-devel pkg-config # for documents BuildRequires: xmlto +%if %suse_version > 1030 BuildRequires: fop BuildRequires: latex2html +%endif %define use_snapshot 0 -License: GPLv2+ -Version: 1.1 +License: GPL v2 or later +Version: 1.0 Release: 1 Summary: Documents and examples for systemtap Group: Development/Tools/Debuggers @@ -37,7 +39,7 @@ Url: http://sourceware.org/systemtap/ %define package_version %{version} %endif Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 -Patch1: systemtap-docdir-fix.diff +Patch: systemtap-docdir-fix.diff Patch2: systemtap-xmlto-fop.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch @@ -61,8 +63,10 @@ Authors: %else %setup -n systemtap-%{package_version} -q %endif -%patch1 -p1 +%patch -p1 +%if %suse_version > 1030 %patch2 -p1 +%endif %build autoreconf -fi @@ -70,9 +74,12 @@ autoreconf -fi make %{?jobs:-j %jobs} %install +%if %suse_version < 1030 +# workaround for old autoconf +export MKDIR_P="mkdir -p" +%endif %makeinstall doc -# COPYING packaged by main spec -cp README AUTHORS NEWS $RPM_BUILD_ROOT%{_docdir}/systemtap/ +cp README AUTHORS NEWS COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ # remove binaries and runtime stuff rm -rf $RPM_BUILD_ROOT%{_bindir} rm -rf $RPM_BUILD_ROOT%{_libexecdir} diff --git a/systemtap-ioblock-suse-kernel-fix.diff b/systemtap-ioblock-suse-kernel-fix.diff index 3f12a69..e274cd6 100644 --- a/systemtap-ioblock-suse-kernel-fix.diff +++ b/systemtap-ioblock-suse-kernel-fix.diff @@ -1,10 +1,6 @@ ---- - tapset/ioblock.stp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/tapset/ioblock.stp -+++ b/tapset/ioblock.stp -@@ -118,7 +118,7 @@ probe ioblock.request = kernel.function +--- a/tapset/ioblock.stp-dist 2008-12-05 08:14:19.000000000 +0100 ++++ b/tapset/ioblock.stp 2008-12-05 08:14:27.000000000 +0100 +@@ -122,7 +122,7 @@ vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments @@ -13,7 +9,7 @@ hw_segments = $bio->bi_hw_segments %) size = $bio->bi_size -@@ -169,7 +169,7 @@ probe ioblock.end = kernel.function("bio +@@ -178,7 +178,7 @@ vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments diff --git a/systemtap-prevent-nested-arg.diff b/systemtap-prevent-nested-arg.diff deleted file mode 100644 index 8633db2..0000000 --- a/systemtap-prevent-nested-arg.diff +++ /dev/null @@ -1,182 +0,0 @@ -From: Josh Stone -Date: Tue Jan 19 15:36:35 2010 -0800 -Git-Repo: git://sources.redhat.com/git/systemtap.git -Git-Commit: 9300f661214a4f4dfac75878485867b30c7db389 -Signed-Off-By: Tony Jones - - tonyj: this fixes parse errors such as: - parse error: expected 'probe', 'global', 'function', or '%{' - saw: identifier '?robe' at - - ------------------------------------------------- - PR11195: Prevent all nested argument substitution - - Our existing protection only made sure that the first token in a - substitution wasn't a nested substitution. That's not sufficient when - there could be multiple tokens involved. This patch makes sure that no - nested tokens are ever allowed to be argument substitutions. - - This also adds a cursor_suspended_line/column and resets the main - cursor_line/column to the beginning of the substitution, so errors will - point a little closer to the right place. - -diff --git a/parse.cxx b/parse.cxx -index edb1927..2688d6d 100644 ---- a/parse.cxx -+++ b/parse.cxx -@@ -632,7 +632,8 @@ parser::peek_kw (std::string const & kw) - - lexer::lexer (istream& input, const string& in, systemtap_session& s): - input_name (in), input_pointer (0), input_end (0), -- cursor_suspend_count(0), cursor_line (1), cursor_column (1), -+ cursor_suspend_count(0), cursor_suspend_line (1), cursor_suspend_column (1), -+ cursor_line (1), cursor_column (1), - session(s), current_file (0) - { - getline(input, input_contents, '\0'); -@@ -693,9 +694,15 @@ lexer::input_get () - ++input_pointer; - - if (cursor_suspend_count) -- // Track effect of input_put: preserve previous cursor/line_column -- // until all of its characters are consumed. -- cursor_suspend_count --; -+ { -+ // Track effect of input_put: preserve previous cursor/line_column -+ // until all of its characters are consumed. -+ if (--cursor_suspend_count == 0) -+ { -+ cursor_line = cursor_suspend_line; -+ cursor_column = cursor_suspend_column; -+ } -+ } - else - { - // update source cursor -@@ -714,12 +721,16 @@ lexer::input_get () - - - void --lexer::input_put (const string& chars) -+lexer::input_put (const string& chars, const token* t) - { - size_t pos = input_pointer - input_contents.data(); - // clog << "[put:" << chars << " @" << pos << "]"; - input_contents.insert (pos, chars); - cursor_suspend_count += chars.size(); -+ cursor_suspend_line = cursor_line; -+ cursor_suspend_column = cursor_column; -+ cursor_line = t->location.line; -+ cursor_column = t->location.column; - input_pointer = input_contents.data() + pos; - input_end = input_contents.data() + input_contents.size(); - } -@@ -731,19 +742,11 @@ lexer::scan (bool wildcard) - token* n = new token; - n->location.file = current_file; - -- unsigned semiskipped_p = 0; -- -- skip: -+skip: -+ bool suspended = (cursor_suspend_count > 0); - n->location.line = cursor_line; - n->location.column = cursor_column; - -- semiskip: -- if (semiskipped_p > 1) -- { -- input_get (); -- throw parse_error ("invalid nested substitution of command line arguments"); -- } -- - int c = input_get(); - // clog << "{" << (char)c << (char)c2 << "}"; - if (c < 0) -@@ -762,38 +765,41 @@ lexer::scan (bool wildcard) - // characters; @1..@999 are quoted/escaped as strings. - // $# and @# expand to the number of arguments, similarly - // raw or quoted. -- if ((c == '$' || c == '@') && -- (c2 == '#')) -+ if ((c == '$' || c == '@') && (c2 == '#')) - { -+ n->content.push_back (c); -+ n->content.push_back (c2); - input_get(); // swallow '#' -- stringstream converter; -- converter << session.args.size (); -- if (c == '$') input_put (converter.str()); -- else input_put (lex_cast_qstring (converter.str())); -- semiskipped_p ++; -- goto semiskip; -+ if (suspended) -+ throw parse_error ("invalid nested substitution of command line arguments", n); -+ size_t num_args = session.args.size (); -+ input_put ((c == '$') ? lex_cast (num_args) : lex_cast_qstring (num_args), n); -+ n->content.clear(); -+ goto skip; - } -- else if ((c == '$' || c == '@') && -- (isdigit (c2))) -+ else if ((c == '$' || c == '@') && (isdigit (c2))) - { -+ n->content.push_back (c); - unsigned idx = 0; - do - { - input_get (); - idx = (idx * 10) + (c2 - '0'); -+ n->content.push_back (c2); - c2 = input_peek (); - } while (c2 > 0 && - isdigit (c2) && - idx <= session.args.size()); // prevent overflow -+ if (suspended) -+ throw parse_error ("invalid nested substitution of command line arguments", n); - if (idx == 0 || - idx-1 >= session.args.size()) - throw parse_error ("command line argument index " + lex_cast(idx) - + " out of range [1-" + lex_cast(session.args.size()) + "]", n); -- string arg = session.args[idx-1]; -- if (c == '$') input_put (arg); -- else input_put (lex_cast_qstring (arg)); -- semiskipped_p ++; -- goto semiskip; -+ const string& arg = session.args[idx-1]; -+ input_put ((c == '$') ? arg : lex_cast_qstring (arg), n); -+ n->content.clear(); -+ goto skip; - } - - else if (isalpha (c) || c == '$' || c == '@' || c == '_' || -diff --git a/parse.h b/parse.h -index 5587586..0ff8664 100644 ---- a/parse.h -+++ b/parse.h -@@ -79,12 +79,14 @@ public: - private: - inline int input_get (); - inline int input_peek (unsigned n=0); -- void input_put (const std::string&); -+ void input_put (const std::string&, const token*); - std::string input_name; - std::string input_contents; - const char *input_pointer; // index into input_contents - const char *input_end; - unsigned cursor_suspend_count; -+ unsigned cursor_suspend_line; -+ unsigned cursor_suspend_column; - unsigned cursor_line; - unsigned cursor_column; - systemtap_session& session; -diff --git a/testsuite/parseko/preprocess16.stp b/testsuite/parseko/preprocess16.stp -new file mode 100755 -index 0000000..364bad6 ---- /dev/null -+++ b/testsuite/parseko/preprocess16.stp -@@ -0,0 +1,4 @@ -+#! /bin/sh -+ -+# recursive after the first token (PR11195) -+stap -p1 -e 'probe begin {$1}' 'x $1' diff --git a/systemtap-xmlto-fop.diff b/systemtap-xmlto-fop.diff index 3558809..033f8fb 100644 --- a/systemtap-xmlto-fop.diff +++ b/systemtap-xmlto-fop.diff @@ -4,14 +4,14 @@ --- a/doc/SystemTap_Tapset_Reference/Makefile.am +++ b/doc/SystemTap_Tapset_Reference/Makefile.am -@@ -43,7 +43,9 @@ stamp-htmldocs: tapsets.xml +@@ -34,7 +34,9 @@ # bump up the allocated space so "xmlto pdf" works tapsets.pdf: tapsets.xml -- env pool_size=2000000 hash_extra=2000000 xmlto $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 -+# env pool_size=2000000 hash_extra=2000000 xmlto $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 +- env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml ++# env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml + xmlto fo tapsets.xml + fop tapsets.fo tapsets.pdf stamp-mandocs: tapsets.xml - xmlto $(XMLTOMANPARAMS) man -o man3 tapsets.xml >/dev/null 2>&1 + xmlto man -o man3 tapsets.xml diff --git a/systemtap.changes b/systemtap.changes index e1bf13e..94c39a9 100644 --- a/systemtap.changes +++ b/systemtap.changes @@ -1,16 +1,3 @@ -------------------------------------------------------------------- -Thu Mar 11 23:56:17 UTC 2010 - tonyj@novell.com - -- Add dependancies for systemtap shell scripts (coreutils, zip, avahi) - -------------------------------------------------------------------- -Thu Mar 11 22:47:15 UTC 2010 - tonyj@novell.com - -- Update to version 1.1 -- Fixes for CVE-2009-4273 (second part, also known as CVE-2010-0412) and - CVE-2010-0411. -- Fix parsing error (systemtap-prevent-nested-arg.diff) - ------------------------------------------------------------------- Wed Dec 2 23:51:24 UTC 2009 - tonyj@novell.com diff --git a/systemtap.spec b/systemtap.spec index ae93b08..e9214d2 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -1,7 +1,7 @@ # -# spec file for package systemtap (Version 1.1) +# spec file for package systemtap (Version 1.0) # -# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -22,8 +22,8 @@ Name: systemtap BuildRequires: gcc-c++ glib2-devel libcap-devel libebl-devel pkg-config sqlite-devel BuildRequires: mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools %define use_snapshot 0 -License: GPLv2+ -Version: 1.1 +License: GPL v2 or later +Version: 1.0 Release: 1 Summary: Instrumentation System Group: Development/Tools/Debuggers @@ -36,13 +36,11 @@ Url: http://sourceware.org/systemtap/ %define package_version %{version} %endif Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 -# need -docdir patch even though docs are packaged by systemtap-docs.spec -# so that they are installed into directories matching below rm -rf's -Patch1: systemtap-docdir-fix.diff +Patch: systemtap-docdir-fix.diff Patch2: systemtap-ioblock-suse-kernel-fix.diff -Patch3: systemtap-CVE-2009-4273.diff -Patch4: systemtap-CVE-2010-0411.diff -Patch5: systemtap-prevent-nested-arg.diff +Patch3: systemtap-CVE-limit-dwarf-expression-stack-size.patch +Patch4: systemtap-CVE-limit-printf-arguments.patch +Patch5: systemtap-CVE-unwind-table-size-checks.patch Requires: libebl1 Requires: %{name}-runtime = %{version}-%{release} @@ -63,7 +61,7 @@ Authors: Tom Zanussi %package runtime -License: GPLv2+ +License: GPL v2 or later Group: Development/Tools/Debuggers Summary: Runtime environment for systemtap @@ -81,12 +79,10 @@ Authors: Tom Zanussi %package client -License: GPLv2+ +License: GPL v2 or later Group: Development/Tools/Debuggers Summary: Systemtap client Requires: %{name}-runtime = %{version}-%{release} -# dependancies for systemtap shell scripts -Requires: coreutils avahi avahi-utils mozilla-nss-tools zip unzip %description client SystemTap is an instrumentation system for systems running Linux 2.6. @@ -102,12 +98,10 @@ Authors: Tom Zanussi %package server -License: GPLv2+ +License: GPL v2 or later Group: Development/Tools/Debuggers Summary: Systemtap server Requires: %{name} = %{version}-%{release} -# dependancies for systemtap shell scripts -Requires: coreutils avahi avahi-utils mozilla-nss-tools zip unzip %description server SystemTap is an instrumentation system for systems running Linux 2.6. @@ -123,7 +117,7 @@ Authors: Tom Zanussi %package sdt-devel -License: GPLv2+ +License: GPL v2 or later Group: Development/Tools/Debuggers Summary: Static probe support tools Requires: %{name} = %{version}-%{release} @@ -147,7 +141,7 @@ Authors: %else %setup -n %{name}-%{package_version} -q %endif -%patch1 -p1 +%patch -p1 %patch2 -p1 %patch3 -p1 %patch4 -p1 @@ -159,19 +153,16 @@ autoreconf -fi make %{?jobs:-j %jobs} %install +%if %suse_version < 1030 +# workaround for old autoconf +export MKDIR_P="mkdir -p" +%endif %makeinstall -# XXX -rm -f $RPM_BUILD_ROOT/usr/lib/systemtap/stap-server-request -# README, AUTHORS, NEWS, man3 and all examples packaged by systemtap-docs -# COPYING needs to stay in main for GPL -rm -rf $RPM_BUILD_ROOT%{_docdir}/systemtap/ +mkdir -p $RPM_BUILD_ROOT/var/cache/systemtap +# doc subpackage is built separetely +# cp README AUTHORS NEWS COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ +rm -rf $RPM_BUILD_ROOT%{_docdir}/systemtap rm -rf $RPM_BUILD_ROOT%{_mandir}/man3 -mkdir -p $RPM_BUILD_ROOT%{_docdir}/systemtap/ -cp COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ -mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/cache/systemtap -mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/systemtap -mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/log -touch $RPM_BUILD_ROOT%{_localstatedir}/log/stap-server.log %clean rm -rf ${RPM_BUILD_ROOT} @@ -180,51 +171,37 @@ rm -rf ${RPM_BUILD_ROOT} %defattr(-,root,root) %{_bindir}/stap %{_mandir}/man1/* -%dir %{_datadir}/%{name} -%{_datadir}/%{name}/runtime -%{_datadir}/%{name}/tapset -#packaged by systemtap-initscript in upstream -%dir %{_localstatedir}/cache/systemtap -%dir %{_localstatedir}/run/systemtap +%{_datadir}/systemtap +%dir %attr(0755,root,root) /var/cache/systemtap %files runtime %defattr(-,root,root) -%doc %{_docdir}/systemtap %{_bindir}/staprun %{_bindir}/stap-report -%{_bindir}/stap-authorize-signing-cert -%dir %{_libexecdir}/%{name} -%{_libexecdir}/%{name}/stapio -%{_libexecdir}/%{name}/stap-env -%{_libexecdir}/%{name}/stap-authorize-cert -%{_mandir}/man8/staprun.8* -%{_mandir}/man8/stap-authorize-signing-cert.8* +%{_libexecdir}/systemtap +%{_mandir}/man8/staprun.* %files client %defattr(-,root,root) -%defattr(-,root,root) %{_bindir}/stap-client -%{_bindir}/stap-authorize-server-cert -%{_libexecdir}/%{name}/stap-find-servers -%{_libexecdir}/%{name}/stap-client-connect -%{_mandir}/man8/stap-client.8* -%{_mandir}/man8/stap-authorize-server-cert.8* +%{_bindir}/stap-find-servers +%{_bindir}/stap-find-or-start-server +%{_bindir}/stap-start-server +%{_bindir}/stap-client-connect +%{_bindir}/stap-env %files server %defattr(-,root,root) -%{_bindir}/stap-authorize-server-cert %{_bindir}/stap-server -%{_libexecdir}/%{name}/stap-serverd -%{_libexecdir}/%{name}/stap-start-server -%{_libexecdir}/%{name}/stap-find-servers -%{_libexecdir}/%{name}/stap-find-or-start-server -%{_libexecdir}/%{name}/stap-stop-server -%{_libexecdir}/%{name}/stap-gen-cert -%{_libexecdir}/%{name}/stap-server-connect -%{_libexecdir}/%{name}/stap-sign-module -%{_mandir}/man8/stap-server.8* -%{_mandir}/man8/stap-authorize-server-cert.8* -%ghost %{_localstatedir}/log/stap-server.log +%{_bindir}/stap-serverd +%{_bindir}/stap-start-server +%{_bindir}/stap-stop-server +%{_bindir}/stap-server-connect +%{_bindir}/stap-authorize* +%{_bindir}/stap-env +%{_bindir}/stap-gen-cert +%{_bindir}/stap-sign-module +%{_mandir}/man8/stap-server.* %files sdt-devel %defattr(-,root,root) From a9cdc7d2f904cd87f91c23344faa76eb2646445616adcd4525bdc235cb0c1e6d Mon Sep 17 00:00:00 2001 From: OBS User autobuild Date: Tue, 8 Dec 2009 11:19:12 +0000 Subject: [PATCH 2/8] checked in OBS-URL: https://build.opensuse.org/package/show/devel:tools/systemtap?expand=0&rev=8 --- systemtap-0.9.9.tar.bz2 | 3 + systemtap-1.0.tar.bz2 | 3 - ...VE-limit-dwarf-expression-stack-size.patch | 135 ------------ systemtap-CVE-limit-printf-arguments.patch | 75 ------- systemtap-CVE-unwind-table-size-checks.patch | 193 ------------------ systemtap-docs.changes | 10 - systemtap-docs.spec | 8 +- systemtap-ioblock-suse-kernel-fix.diff | 4 +- systemtap.changes | 35 ---- systemtap.spec | 18 +- 10 files changed, 17 insertions(+), 467 deletions(-) create mode 100644 systemtap-0.9.9.tar.bz2 delete mode 100644 systemtap-1.0.tar.bz2 delete mode 100644 systemtap-CVE-limit-dwarf-expression-stack-size.patch delete mode 100644 systemtap-CVE-limit-printf-arguments.patch delete mode 100644 systemtap-CVE-unwind-table-size-checks.patch diff --git a/systemtap-0.9.9.tar.bz2 b/systemtap-0.9.9.tar.bz2 new file mode 100644 index 0000000..38f3a14 --- /dev/null +++ b/systemtap-0.9.9.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c57c639399982ad2d0f6e903066397a7cac0b99babdaa611901b5d3083ffabb6 +size 1172877 diff --git a/systemtap-1.0.tar.bz2 b/systemtap-1.0.tar.bz2 deleted file mode 100644 index 54bc50d..0000000 --- a/systemtap-1.0.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9a942ba85d6360023e6f8503a8dd4c8493d16b17cb474cc8f0ad5a50cec3607a -size 1205746 diff --git a/systemtap-CVE-limit-dwarf-expression-stack-size.patch b/systemtap-CVE-limit-dwarf-expression-stack-size.patch deleted file mode 100644 index 4394e4f..0000000 --- a/systemtap-CVE-limit-dwarf-expression-stack-size.patch +++ /dev/null @@ -1,135 +0,0 @@ -From: Jan Lieskovsky -Subject: Three SystemTap-1.0 denial of service issues -References: CVE-2009-2911, BNC#548361 -Upstream: yes - - Three denial of service flaws were found in the SystemTap -instrumentation system of version 1.0, when the --unprivileged mode was -activated: - -b, Kernel stack frame overflow allows local attackers to cause denial -of service via specially-crafted user-provided DWARF information. - -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/systemtap-CVE-limit-printf-arguments.patch b/systemtap-CVE-limit-printf-arguments.patch deleted file mode 100644 index 32041a0..0000000 --- a/systemtap-CVE-limit-printf-arguments.patch +++ /dev/null @@ -1,75 +0,0 @@ -From: Jan Lieskovsky -Subject: Three SystemTap-1.0 denial of service issues -References: CVE-2009-2911, BNC#548361 -Upstream: yes - - Three denial of service flaws were found in the SystemTap -instrumentation system of version 1.0, when the --unprivileged mode was -activated: - -a, Kernel stack overflow allows local attackers to cause denial of service or -execute arbitrary code via long number of parameters, provided to the print* -call. - -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 tmp; - - diff --git a/systemtap-CVE-unwind-table-size-checks.patch b/systemtap-CVE-unwind-table-size-checks.patch deleted file mode 100644 index 408239b..0000000 --- a/systemtap-CVE-unwind-table-size-checks.patch +++ /dev/null @@ -1,193 +0,0 @@ -From: Jan Lieskovsky -Subject: Three SystemTap-1.0 denial of service issues -References: CVE-2009-2911, BNC#548361 -Upstream: yes - - Three denial of service flaws were found in the SystemTap -instrumentation system of version 1.0, when the --unprivileged mode was -activated: - -c, Absent check(s) for the upper bound of the size of the unwind table - and for the upper bound of the size of each of the CIE/CFI records, could - allow an attacker to cause a denial of service (infinite loop). - -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 != ¬_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 == ¬_fde || (ptrType = fde_pointer_type(cie)) < 0) -+ if (cie == NULL || cie == ¬_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 - } - -+// 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/systemtap-docs.changes b/systemtap-docs.changes index 8573048..5a19578 100644 --- a/systemtap-docs.changes +++ b/systemtap-docs.changes @@ -1,13 +1,3 @@ -------------------------------------------------------------------- -Wed Dec 2 23:52:10 UTC 2009 - tonyj@novell.com - -- Minor changes to spec file - -------------------------------------------------------------------- -Fri Oct 2 18:57:14 CEST 2009 - tonyj@suse.de - -- updated to version 1.0. See systemtap.changes for full changelog. - ------------------------------------------------------------------- Tue Jul 21 08:47:33 CEST 2009 - tiwai@suse.de diff --git a/systemtap-docs.spec b/systemtap-docs.spec index f29e359..9501344 100644 --- a/systemtap-docs.spec +++ b/systemtap-docs.spec @@ -28,7 +28,7 @@ BuildRequires: latex2html %endif %define use_snapshot 0 License: GPL v2 or later -Version: 1.0 +Version: 0.9.9 Release: 1 Summary: Documents and examples for systemtap Group: Development/Tools/Debuggers @@ -40,7 +40,8 @@ Url: http://sourceware.org/systemtap/ %endif Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 Patch: systemtap-docdir-fix.diff -Patch2: systemtap-xmlto-fop.diff +# Patch2: systemtap-ioblock-suse-kernel-fix.diff +Patch3: systemtap-xmlto-fop.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch @@ -64,8 +65,9 @@ Authors: %setup -n systemtap-%{package_version} -q %endif %patch -p1 +# %patch2 %if %suse_version > 1030 -%patch2 -p1 +%patch3 -p1 %endif %build diff --git a/systemtap-ioblock-suse-kernel-fix.diff b/systemtap-ioblock-suse-kernel-fix.diff index e274cd6..7b8f2f7 100644 --- a/systemtap-ioblock-suse-kernel-fix.diff +++ b/systemtap-ioblock-suse-kernel-fix.diff @@ -1,5 +1,5 @@ ---- a/tapset/ioblock.stp-dist 2008-12-05 08:14:19.000000000 +0100 -+++ b/tapset/ioblock.stp 2008-12-05 08:14:27.000000000 +0100 +--- tapset/ioblock.stp-dist 2008-12-05 08:14:19.000000000 +0100 ++++ tapset/ioblock.stp 2008-12-05 08:14:27.000000000 +0100 @@ -122,7 +122,7 @@ vcnt = $bio->bi_vcnt idx = $bio->bi_idx diff --git a/systemtap.changes b/systemtap.changes index 94c39a9..8a4555d 100644 --- a/systemtap.changes +++ b/systemtap.changes @@ -1,38 +1,3 @@ -------------------------------------------------------------------- -Wed Dec 2 23:51:24 UTC 2009 - tonyj@novell.com - -- Fixes for CVE-2009-2911, BNC#548361 - -------------------------------------------------------------------- -Fri Oct 2 18:57:14 CEST 2009 - tonyj@suse.de - -- updated to version 1.0: - * SystemTap frontend (stap) changes - - EXPERIMENTAL support for unprivileged users. - - -a ARCH allows cross compiling of scripts, stap-start-server arguments - extended to support starting a cross compiling server - - Change notion of architecture to be same as kernels - - Support output file switching by SIGUSR2 - - New experimental transport mechanism using ftrace's ring_buffer - - Reduction in memory consumption for scripts using many uprobes - - Support for recognizing DW_OP_{stack,implicit}_value DWARF expressions - * SystemTap script language changes - - Dwarf probes now support C++ scopes and so can be limited to classes or - namespaces. - - Preprocessor support for || and && - - Probe alias names may be overloaded (multiple aliases of same name) - * SystemTap tapset changes - - Enabling semaphore now used to reduce computation overhead of dorman - process().mark() probes. - - Many functions marked as usable by unprivileged users (return global info - or specific to user process). - - New netdev tapset probe points for monitoring network traffic and device - configurations. - - New task_backtrace function returns the current hex backtrace of any - arbitrary task in the system. - - Function is_myproc returns whether the current process is owned by user - which started systemtap script. - ------------------------------------------------------------------- Thu Aug 13 15:55:14 CEST 2009 - tiwai@suse.de diff --git a/systemtap.spec b/systemtap.spec index e9214d2..62866e8 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -1,5 +1,5 @@ # -# spec file for package systemtap (Version 1.0) +# spec file for package systemtap (Version 0.9.9) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -23,7 +23,7 @@ BuildRequires: gcc-c++ glib2-devel libcap-devel libebl-devel pkg-config sqlite- BuildRequires: mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools %define use_snapshot 0 License: GPL v2 or later -Version: 1.0 +Version: 0.9.9 Release: 1 Summary: Instrumentation System Group: Development/Tools/Debuggers @@ -38,10 +38,7 @@ Url: http://sourceware.org/systemtap/ Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 Patch: systemtap-docdir-fix.diff Patch2: systemtap-ioblock-suse-kernel-fix.diff -Patch3: systemtap-CVE-limit-dwarf-expression-stack-size.patch -Patch4: systemtap-CVE-limit-printf-arguments.patch -Patch5: systemtap-CVE-unwind-table-size-checks.patch - +# Patch3: systemtap-xmlto-fop.diff Requires: libebl1 Requires: %{name}-runtime = %{version}-%{release} BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -142,10 +139,10 @@ Authors: %setup -n %{name}-%{package_version} -q %endif %patch -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 +%patch2 +# %if %suse_version > 1030 +# %patch3 -p1 +# %endif %build autoreconf -fi @@ -200,7 +197,6 @@ rm -rf ${RPM_BUILD_ROOT} %{_bindir}/stap-authorize* %{_bindir}/stap-env %{_bindir}/stap-gen-cert -%{_bindir}/stap-sign-module %{_mandir}/man8/stap-server.* %files sdt-devel From f843c43c01c34545ff8c76b999a8e8d4535d22b994e675ca77e828a6dbbef9b8 Mon Sep 17 00:00:00 2001 From: Stephan Kulow Date: Fri, 19 Feb 2010 15:14:51 +0000 Subject: [PATCH 3/8] converted link to branch OBS-URL: https://build.opensuse.org/package/show/devel:tools/systemtap?expand=0&rev=9 --- systemtap-0.9.9.tar.bz2 | 3 - systemtap-1.0.tar.bz2 | 3 + ...VE-limit-dwarf-expression-stack-size.patch | 135 ++++++++++++ systemtap-CVE-limit-printf-arguments.patch | 75 +++++++ systemtap-CVE-unwind-table-size-checks.patch | 193 ++++++++++++++++++ systemtap-docs.changes | 10 + systemtap-docs.spec | 12 +- systemtap-ioblock-suse-kernel-fix.diff | 4 +- systemtap.changes | 35 ++++ systemtap.spec | 27 +-- 10 files changed, 473 insertions(+), 24 deletions(-) delete mode 100644 systemtap-0.9.9.tar.bz2 create mode 100644 systemtap-1.0.tar.bz2 create mode 100644 systemtap-CVE-limit-dwarf-expression-stack-size.patch create mode 100644 systemtap-CVE-limit-printf-arguments.patch create mode 100644 systemtap-CVE-unwind-table-size-checks.patch diff --git a/systemtap-0.9.9.tar.bz2 b/systemtap-0.9.9.tar.bz2 deleted file mode 100644 index 38f3a14..0000000 --- a/systemtap-0.9.9.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c57c639399982ad2d0f6e903066397a7cac0b99babdaa611901b5d3083ffabb6 -size 1172877 diff --git a/systemtap-1.0.tar.bz2 b/systemtap-1.0.tar.bz2 new file mode 100644 index 0000000..54bc50d --- /dev/null +++ b/systemtap-1.0.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a942ba85d6360023e6f8503a8dd4c8493d16b17cb474cc8f0ad5a50cec3607a +size 1205746 diff --git a/systemtap-CVE-limit-dwarf-expression-stack-size.patch b/systemtap-CVE-limit-dwarf-expression-stack-size.patch new file mode 100644 index 0000000..4394e4f --- /dev/null +++ b/systemtap-CVE-limit-dwarf-expression-stack-size.patch @@ -0,0 +1,135 @@ +From: Jan Lieskovsky +Subject: Three SystemTap-1.0 denial of service issues +References: CVE-2009-2911, BNC#548361 +Upstream: yes + + Three denial of service flaws were found in the SystemTap +instrumentation system of version 1.0, when the --unprivileged mode was +activated: + +b, Kernel stack frame overflow allows local attackers to cause denial +of service via specially-crafted user-provided DWARF information. + +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/systemtap-CVE-limit-printf-arguments.patch b/systemtap-CVE-limit-printf-arguments.patch new file mode 100644 index 0000000..32041a0 --- /dev/null +++ b/systemtap-CVE-limit-printf-arguments.patch @@ -0,0 +1,75 @@ +From: Jan Lieskovsky +Subject: Three SystemTap-1.0 denial of service issues +References: CVE-2009-2911, BNC#548361 +Upstream: yes + + Three denial of service flaws were found in the SystemTap +instrumentation system of version 1.0, when the --unprivileged mode was +activated: + +a, Kernel stack overflow allows local attackers to cause denial of service or +execute arbitrary code via long number of parameters, provided to the print* +call. + +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 tmp; + + diff --git a/systemtap-CVE-unwind-table-size-checks.patch b/systemtap-CVE-unwind-table-size-checks.patch new file mode 100644 index 0000000..408239b --- /dev/null +++ b/systemtap-CVE-unwind-table-size-checks.patch @@ -0,0 +1,193 @@ +From: Jan Lieskovsky +Subject: Three SystemTap-1.0 denial of service issues +References: CVE-2009-2911, BNC#548361 +Upstream: yes + + Three denial of service flaws were found in the SystemTap +instrumentation system of version 1.0, when the --unprivileged mode was +activated: + +c, Absent check(s) for the upper bound of the size of the unwind table + and for the upper bound of the size of each of the CIE/CFI records, could + allow an attacker to cause a denial of service (infinite loop). + +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 != ¬_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 == ¬_fde || (ptrType = fde_pointer_type(cie)) < 0) ++ if (cie == NULL || cie == ¬_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 + } + ++// 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/systemtap-docs.changes b/systemtap-docs.changes index 5a19578..8573048 100644 --- a/systemtap-docs.changes +++ b/systemtap-docs.changes @@ -1,3 +1,13 @@ +------------------------------------------------------------------- +Wed Dec 2 23:52:10 UTC 2009 - tonyj@novell.com + +- Minor changes to spec file + +------------------------------------------------------------------- +Fri Oct 2 18:57:14 CEST 2009 - tonyj@suse.de + +- updated to version 1.0. See systemtap.changes for full changelog. + ------------------------------------------------------------------- Tue Jul 21 08:47:33 CEST 2009 - tiwai@suse.de diff --git a/systemtap-docs.spec b/systemtap-docs.spec index 9501344..35adc8f 100644 --- a/systemtap-docs.spec +++ b/systemtap-docs.spec @@ -1,5 +1,5 @@ # -# spec file for package systemtap-docs (Version 0.9.9) +# spec file for package systemtap-docs (Version 1.0) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -27,8 +27,8 @@ BuildRequires: fop BuildRequires: latex2html %endif %define use_snapshot 0 -License: GPL v2 or later -Version: 0.9.9 +License: GPLv2+ +Version: 1.0 Release: 1 Summary: Documents and examples for systemtap Group: Development/Tools/Debuggers @@ -40,8 +40,7 @@ Url: http://sourceware.org/systemtap/ %endif Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 Patch: systemtap-docdir-fix.diff -# Patch2: systemtap-ioblock-suse-kernel-fix.diff -Patch3: systemtap-xmlto-fop.diff +Patch2: systemtap-xmlto-fop.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch @@ -65,9 +64,8 @@ Authors: %setup -n systemtap-%{package_version} -q %endif %patch -p1 -# %patch2 %if %suse_version > 1030 -%patch3 -p1 +%patch2 -p1 %endif %build diff --git a/systemtap-ioblock-suse-kernel-fix.diff b/systemtap-ioblock-suse-kernel-fix.diff index 7b8f2f7..e274cd6 100644 --- a/systemtap-ioblock-suse-kernel-fix.diff +++ b/systemtap-ioblock-suse-kernel-fix.diff @@ -1,5 +1,5 @@ ---- tapset/ioblock.stp-dist 2008-12-05 08:14:19.000000000 +0100 -+++ tapset/ioblock.stp 2008-12-05 08:14:27.000000000 +0100 +--- a/tapset/ioblock.stp-dist 2008-12-05 08:14:19.000000000 +0100 ++++ b/tapset/ioblock.stp 2008-12-05 08:14:27.000000000 +0100 @@ -122,7 +122,7 @@ vcnt = $bio->bi_vcnt idx = $bio->bi_idx diff --git a/systemtap.changes b/systemtap.changes index 8a4555d..94c39a9 100644 --- a/systemtap.changes +++ b/systemtap.changes @@ -1,3 +1,38 @@ +------------------------------------------------------------------- +Wed Dec 2 23:51:24 UTC 2009 - tonyj@novell.com + +- Fixes for CVE-2009-2911, BNC#548361 + +------------------------------------------------------------------- +Fri Oct 2 18:57:14 CEST 2009 - tonyj@suse.de + +- updated to version 1.0: + * SystemTap frontend (stap) changes + - EXPERIMENTAL support for unprivileged users. + - -a ARCH allows cross compiling of scripts, stap-start-server arguments + extended to support starting a cross compiling server + - Change notion of architecture to be same as kernels + - Support output file switching by SIGUSR2 + - New experimental transport mechanism using ftrace's ring_buffer + - Reduction in memory consumption for scripts using many uprobes + - Support for recognizing DW_OP_{stack,implicit}_value DWARF expressions + * SystemTap script language changes + - Dwarf probes now support C++ scopes and so can be limited to classes or + namespaces. + - Preprocessor support for || and && + - Probe alias names may be overloaded (multiple aliases of same name) + * SystemTap tapset changes + - Enabling semaphore now used to reduce computation overhead of dorman + process().mark() probes. + - Many functions marked as usable by unprivileged users (return global info + or specific to user process). + - New netdev tapset probe points for monitoring network traffic and device + configurations. + - New task_backtrace function returns the current hex backtrace of any + arbitrary task in the system. + - Function is_myproc returns whether the current process is owned by user + which started systemtap script. + ------------------------------------------------------------------- Thu Aug 13 15:55:14 CEST 2009 - tiwai@suse.de diff --git a/systemtap.spec b/systemtap.spec index 62866e8..013bca5 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -1,5 +1,5 @@ # -# spec file for package systemtap (Version 0.9.9) +# spec file for package systemtap (Version 1.0) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -22,8 +22,8 @@ Name: systemtap BuildRequires: gcc-c++ glib2-devel libcap-devel libebl-devel pkg-config sqlite-devel BuildRequires: mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools %define use_snapshot 0 -License: GPL v2 or later -Version: 0.9.9 +License: GPLv2+ +Version: 1.0 Release: 1 Summary: Instrumentation System Group: Development/Tools/Debuggers @@ -38,7 +38,9 @@ Url: http://sourceware.org/systemtap/ Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 Patch: systemtap-docdir-fix.diff Patch2: systemtap-ioblock-suse-kernel-fix.diff -# Patch3: systemtap-xmlto-fop.diff +Patch3: systemtap-CVE-limit-dwarf-expression-stack-size.patch +Patch4: systemtap-CVE-limit-printf-arguments.patch +Patch5: systemtap-CVE-unwind-table-size-checks.patch Requires: libebl1 Requires: %{name}-runtime = %{version}-%{release} BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -58,7 +60,7 @@ Authors: Tom Zanussi %package runtime -License: GPL v2 or later +License: GPLv2+ Group: Development/Tools/Debuggers Summary: Runtime environment for systemtap @@ -76,7 +78,7 @@ Authors: Tom Zanussi %package client -License: GPL v2 or later +License: GPLv2+ Group: Development/Tools/Debuggers Summary: Systemtap client Requires: %{name}-runtime = %{version}-%{release} @@ -95,7 +97,7 @@ Authors: Tom Zanussi %package server -License: GPL v2 or later +License: GPLv2+ Group: Development/Tools/Debuggers Summary: Systemtap server Requires: %{name} = %{version}-%{release} @@ -114,7 +116,7 @@ Authors: Tom Zanussi %package sdt-devel -License: GPL v2 or later +License: GPLv2+ Group: Development/Tools/Debuggers Summary: Static probe support tools Requires: %{name} = %{version}-%{release} @@ -139,10 +141,10 @@ Authors: %setup -n %{name}-%{package_version} -q %endif %patch -p1 -%patch2 -# %if %suse_version > 1030 -# %patch3 -p1 -# %endif +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch5 -p1 %build autoreconf -fi @@ -197,6 +199,7 @@ rm -rf ${RPM_BUILD_ROOT} %{_bindir}/stap-authorize* %{_bindir}/stap-env %{_bindir}/stap-gen-cert +%{_bindir}/stap-sign-module %{_mandir}/man8/stap-server.* %files sdt-devel From 5165295d2f6a231a5881d7ca5403bb20c819eaca0b89536bee425587ff656816 Mon Sep 17 00:00:00 2001 From: Tony Jones Date: Fri, 12 Mar 2010 00:04:39 +0000 Subject: [PATCH 4/8] Accepting request 34652 from home:jones_tony:Factory Copy from home:jones_tony:Factory/systemtap via accept of submit request 34652 revision 6. Request was accepted with message: OBS-URL: https://build.opensuse.org/request/show/34652 OBS-URL: https://build.opensuse.org/package/show/devel:tools/systemtap?expand=0&rev=10 --- systemtap-1.0.tar.bz2 | 3 - systemtap-1.1.tar.bz2 | 3 + systemtap-CVE-2009-4273.diff | 925 ++++++++++++++++++ systemtap-CVE-2010-0411.diff | 187 ++++ ...VE-limit-dwarf-expression-stack-size.patch | 135 --- systemtap-CVE-limit-printf-arguments.patch | 75 -- systemtap-CVE-unwind-table-size-checks.patch | 193 ---- systemtap-docdir-fix.diff | 17 +- systemtap-docs.changes | 5 + systemtap-docs.spec | 19 +- systemtap-ioblock-suse-kernel-fix.diff | 12 +- systemtap-prevent-nested-arg.diff | 182 ++++ systemtap-xmlto-fop.diff | 8 +- systemtap.changes | 13 + systemtap.spec | 94 +- 15 files changed, 1404 insertions(+), 467 deletions(-) delete mode 100644 systemtap-1.0.tar.bz2 create mode 100644 systemtap-1.1.tar.bz2 create mode 100644 systemtap-CVE-2009-4273.diff create mode 100644 systemtap-CVE-2010-0411.diff delete mode 100644 systemtap-CVE-limit-dwarf-expression-stack-size.patch delete mode 100644 systemtap-CVE-limit-printf-arguments.patch delete mode 100644 systemtap-CVE-unwind-table-size-checks.patch create mode 100644 systemtap-prevent-nested-arg.diff diff --git a/systemtap-1.0.tar.bz2 b/systemtap-1.0.tar.bz2 deleted file mode 100644 index 54bc50d..0000000 --- a/systemtap-1.0.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9a942ba85d6360023e6f8503a8dd4c8493d16b17cb474cc8f0ad5a50cec3607a -size 1205746 diff --git a/systemtap-1.1.tar.bz2 b/systemtap-1.1.tar.bz2 new file mode 100644 index 0000000..073b472 --- /dev/null +++ b/systemtap-1.1.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d620a9861cd7c9609fb8012faf20eafb632f3f3a919bf0c08bec3a14924e3a2 +size 1293846 diff --git a/systemtap-CVE-2009-4273.diff b/systemtap-CVE-2009-4273.diff new file mode 100644 index 0000000..005f70a --- /dev/null +++ b/systemtap-CVE-2009-4273.diff @@ -0,0 +1,925 @@ +Subject: VUL-0: systemtap-server code exec +References: bnc#574243 +Signed-Off-By: Tony Jones + +Fix remaining portions of this CVE (part2) still present post release-1.1 +This second part is also referred to as CVE-2010-0412 + +Covers cases such as stap-client -B CC=/bin/rm CFLAGS=/ ... where the +execution is done by make + + + +commit b75067caf1bb416af21473e40c917d953531e9f9 +Author: Dave Brolley +Date: Mon Jan 18 11:56:13 2010 -0500 + + Correct client-side quoting issues discovered by fche during the server-side reimplementation. + + Also add the test cases to the test suite. + +commit 241443ad36a5a2cacb9e8e6f12f808d304835f2a +Author: Dave Brolley +Date: Tue Feb 2 08:26:01 2010 -0500 + + PR 11105: Remaining client-side problems: + + stap-client: Correct handling of embedded newlines in arguments. + server_args.exp: Add additional cases discovered by fche and by fuzzing. + +commit 4240be911e37b817727ecb33f321f0ea389ede61 +Author: Dave Brolley +Date: Mon Feb 15 15:01:28 2010 -0500 + + Don't pass client-only options to the server. + + Also correct parsing of the --server option. + +commit d2334a2233f4efd055dab021c603f7c046730a66 +Author: Dave Brolley +Date: Tue Feb 2 14:08:31 2010 -0500 + + Compile server logging and robustness. + + Log certificate location and status when starting server. + Additional care in handling arguments in stap-serverd. + New test case discovered by fuzzing added and fixed. + +commit c0d1b5a004b9949bb455b7dbe17b335b7cab9ead +Author: Frank Ch. Eigler +Date: Fri Feb 12 10:25:43 2010 -0500 + + PR11105 part 2: tighten constraints on stap-server parameters passed to make + + * util.h, util.cxx (assert_match_regexp): New function. + * main.cxx (main): Constrain -R, -r, -a, -D, -S, -q, -B flags. + * stap-serverd (listen): Harden stap-server-connect with ulimit/loop. + * testsuite/systemtap.server/{client,server}_args.exp: Revised. + +commit cc9e5488d82b728e568bca1f8d6094856fc8e641 +Author: Frank Ch. Eigler +Date: Fri Feb 12 10:39:58 2010 -0500 + + PR11105 part 2a, fix buggy \\. in -r option regexp + +--- + main.cxx | 24 ++-- + stap-client | 151 +++++++++++++++++------------ + stap-gen-cert | 43 ++++---- + stap-serverd | 40 +++++-- + testsuite/systemtap.server/client_args.exp | 28 ++--- + testsuite/systemtap.server/hello.stp | 2 + testsuite/systemtap.server/server_args.exp | 49 +++++---- + util.cxx | 36 ++++++ + util.h | 2 + 9 files changed, 238 insertions(+), 137 deletions(-) + +--- a/main.cxx ++++ b/main.cxx +@@ -57,7 +57,7 @@ version () + << "SystemTap translator/driver " + << "(version " << VERSION << "/" << dwfl_version (NULL) + << " " << GIT_MESSAGE << ")" << endl +- << "Copyright (C) 2005-2009 Red Hat, Inc. and others" << endl ++ << "Copyright (C) 2005-2010 Red Hat, Inc. and others" << endl + << "This is free software; see the source for copying conditions." << endl; + } + +@@ -670,12 +670,12 @@ main (int argc, char * const argv []) + break; + + case 'o': ++ // NB: client_options not a problem, since pass 1-4 does not use output_file. + s.output_file = string (optarg); + break; + + case 'R': +- if (client_options) +- client_options_disallowed += client_options_disallowed.empty () ? "-R" : ", -R"; ++ if (client_options) { cerr << "ERROR: -R invalid with --client-options" << endl; usage(s,1); } + s.runtime_path = string (optarg); + break; + +@@ -684,6 +684,7 @@ main (int argc, char * const argv []) + client_options_disallowed += client_options_disallowed.empty () ? "-m" : ", -m"; + s.module_name = string (optarg); + save_module = true; ++ // XXX: convert to assert_regexp_match() + { + string::size_type len = s.module_name.length(); + +@@ -728,15 +729,14 @@ main (int argc, char * const argv []) + break; + + case 'r': +- if (client_options) +- client_options_disallowed += client_options_disallowed.empty () ? "-r" : ", -r"; ++ if (client_options) // NB: no paths! ++ assert_regexp_match("-r parameter from client", optarg, "^[a-z0-9_.-]+$"); + setup_kernel_release(s, optarg); + break; + + case 'a': +- if (client_options) +- client_options_disallowed += client_options_disallowed.empty () ? "-a" : ", -a"; +- s.architecture = string(optarg); ++ assert_regexp_match("-a parameter", optarg, "^[a-z0-9_-]+$"); ++ s.architecture = string(optarg); + break; + + case 'k': +@@ -783,16 +783,19 @@ main (int argc, char * const argv []) + break; + + case 'D': ++ assert_regexp_match ("-D parameter", optarg, "^[a-z_][a-z_0-9]*(=[a-z_0-9]+)?$"); + if (client_options) + client_options_disallowed += client_options_disallowed.empty () ? "-D" : ", -D"; + s.macros.push_back (string (optarg)); + break; + + case 'S': ++ assert_regexp_match ("-S parameter", optarg, "^[0-9]+(,[0-9]+)?$"); + s.size_option = string (optarg); + break; + + case 'q': ++ if (client_options) { cerr << "ERROR: -q invalid with --client-options" << endl; usage(s,1); } + s.tapset_compile_coverage = true; + break; + +@@ -823,9 +826,8 @@ main (int argc, char * const argv []) + break; + + case 'B': +- if (client_options) +- client_options_disallowed += client_options_disallowed.empty () ? "-B" : ", -B"; +- s.kbuildflags.push_back (string (optarg)); ++ if (client_options) { cerr << "ERROR: -B invalid with --client-options" << endl; usage(s,1); } ++ s.kbuildflags.push_back (string (optarg)); + break; + + case 0: +--- a/stap-client ++++ b/stap-client +@@ -2,7 +2,7 @@ + + # Compile server client for systemtap + # +-# Copyright (C) 2008, 2009, 2010 Red Hat Inc. ++# Copyright (C) 2008-2010 Red Hat Inc. + # + # This file is part of systemtap, and is free software. You can + # redistribute it and/or modify it under the terms of the GNU General +@@ -84,34 +84,34 @@ function parse_options { + # Each command line argument will be written to its own file within the + # request package. + argc=1 ++ packed_options='-' + arg_subst= + + while test $# != 0 + do + advance=0 + dash_seen=0 ++ client_arg=0 + + # Start of a new token. + first_token="$1" + until test $advance != 0 + do + # Identify the next option +- first_char=`expr "$first_token" : '\(.\).*'` ++ first_char="${first_token:0:1}" + second_char= + if test $dash_seen = 0; then + if test "$first_char" = "-"; then + if test "$first_token" != "-"; then + # It's not a lone dash, so it's an option. + # Is it a long option (i.e. --option)? +- second_char=`expr "$first_token" : '.\(.\).*'` ++ second_char="${first_token:1:1}" + if test "X$second_char" = "X-"; then +- long_option=`expr "$first_token" : '--\(.*\)=.*'` +- test "X$long_option" != "X" || long_option=`expr "$first_token" : '--\(.*\)'` +- case $long_option in +- ssl) ++ case "$first_token" in ++ --ssl=*) + process_ssl "$first_token" + ;; +- server) ++ --server=*) + process_server "$first_token" + ;; + *) +@@ -123,9 +123,9 @@ function parse_options { + fi + # It's not a lone dash, or a long option, so it's a short option string. + # Remove the dash. +- first_token=`expr "$first_token" : '-\(.*\)'` ++ first_token="${first_token:1}" + dash_seen=1 +- first_char=`expr "$first_token" : '\(.\).*'` ++ first_char="${first_token:0:1}" + fi + fi + if test $dash_seen = 0; then +@@ -145,69 +145,69 @@ function parse_options { + # We are at the start of an option. Look at the first character. + case $first_char in + a) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_a "$stap_arg" + ;; + B) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + c) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_c "$stap_arg" + ;; + D) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + e) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_e "$stap_arg" + ;; + I) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_I "$stap_arg" + ;; + k) + keep_temps=1 + ;; + l) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + p_phase=2 + ;; + L) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + p_phase=2 + ;; + m) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_m "$stap_arg" + ;; + o) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_o "$stap_arg" + ;; + p) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_p "$stap_arg" + ;; + r) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_r "$stap_arg" + ;; + R) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_R "$stap_arg" + ;; + s) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + S) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + v) + v_level=$(($v_level + 1)) + ;; + x) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + *) + # An unknown or unimportant flag. +@@ -216,7 +216,7 @@ function parse_options { + + if test $advance = 0; then + # Just another flag character. Consume it. +- first_token=`expr "$first_token" : '.\(.*\)'` ++ first_token="${first_token:1}" + if test "X$first_token" = "X"; then + advance=$(($advance + 1)) + fi +@@ -224,9 +224,19 @@ function parse_options { + done + + # Consume the arguments we just processed. +- while test $advance != 0 +- do +- # Place the argument is a numbered file within our temp ++ while test $advance != 0; do ++ # Does the final argument file contain a client-side file ++ # name which must be changed to a server-side name? ++ local arg ++ if test "X$arg_subst" != "X" -a $advance = 1; then ++ arg="$arg_subst" ++ arg_subst= ++ else ++ arg="$1" ++ fi ++ ++ # If it's not client-only argument, ++ # place the argument in a numbered file within our temp + # directory. + # o We don't write a newline at the end, since newline could be + # part of the argument. +@@ -234,20 +244,16 @@ function parse_options { + # in order to avoid having 'echo' interpret the output as + # its own option. We then remove the X. + # There must be a better way. +- echo -n "X$1" > "$tmpdir_client/argv$argc" +- sed -i "s|^X||" "$tmpdir_client/argv$argc" +- +- # Does the final argument file contain client-side data +- # which must be changed to server-side data? +- if test "X$arg_subst" != "X" -a $advance = 1; then +- sed -i "s|$stap_arg|$arg_subst|" "$tmpdir_client/argv$argc" +- arg_subst= ++ if test $client_arg = 0; then ++ echo -n "X$arg" > "$tmpdir_client/argv$argc" ++ sed -i "s|^X||" "$tmpdir_client/argv$argc" ++ argc=$(($argc + 1)) + fi + + # Get the next argument. + shift +- argc=$(($argc + 1)) + advance=$(($advance - 1)) ++ packed_options='-' + done + done + +@@ -256,7 +262,8 @@ function parse_options { + if test "X$script_file" != "X"; then + local local_name + if test "$script_file" != "-"; then +- local_name=`generate_client_temp_name "$script_file"` ++ generate_client_temp_name "$script_file" ++ local_name="$client_temp_name" + else + local_name="-" + fi +@@ -277,8 +284,9 @@ function parse_options { + # Collect an argument to the given option + function get_arg { + # Remove first character. +- local opt=`expr "$1" : '\(.\).*'` +- local first=`expr "$1" : '.\(.*\)'` ++ local opt="${1:0:1}" ++ local first="${1:1}" ++ packed_options="${packed_options}$opt" + + # Advance to the next token, if the first one is exhausted. + if test "X$first" = "X"; then +@@ -294,7 +302,8 @@ function get_arg { + # + # Process the --ssl option. + function process_ssl { +- local db=`expr "$1" : '--ssl=\(.*\)'` ++ client_arg=1 ++ local db="${1:6}" + + test "X$db" != "X" || \ + fatal "Missing argument to --ssl" +@@ -308,7 +317,8 @@ function process_ssl { + # + # Process the --server option. + function process_server { +- local spec=`expr "$1" : '--server=\(.*\)'` ++ client_arg=1 ++ local spec="${1:9}" + + test "X$spec" != "X" || \ + fatal "Missing argument to --server" +@@ -335,12 +345,19 @@ function process_e { + fi + } + +-# function: process_I ARGUMENT ++# function: process_I ARGUMENT ORIGINAL_ARGUMENT + # + # Process the -I flag. + function process_I { + test "X$1" = "X" && return +- arg_subst=tapsets/`include_file_or_directory tapsets "$1"` ++ test "${1:0:1}" = " ++" && return ++ include_file_or_directory tapsets "$1" ++ if test $advance = 1; then ++ arg_subst="${packed_options}tapsets/$included_name" ++ else ++ arg_subst="tapsets/$included_name" ++ fi + } + + # function: process_m ARGUMENT +@@ -369,7 +386,7 @@ function process_p { + # + # Process the -r flag. + function process_r { +- local first_char=`expr "$1" : '\(.\).*'` ++ local first_char="${1:0:1}" + + if test "$first_char" = "/"; then # fully specified path + kernel_build_tree="$1" +@@ -402,23 +419,34 @@ function process_a { + fi + } + +-# function: process_R ARGUMENT ++# function: process_R ARGUMENT ORIGINAL_ARGUMENT + # + # Process the -R flag. + function process_R { + test "X$1" = "X" && return +- arg_subst=runtime/`include_file_or_directory runtime "$1"` ++ test "${1:0:1}" = " ++" && return ++ include_file_or_directory runtime "$1" ++ if test $advance = 1; then ++ arg_subst="${packed_options}runtime/$included_name" ++ else ++ arg_subst="runtime/$included_name" ++ fi + } + + # function: include_file_or_directory PREFIX NAME + # + # Include the given file or directory in the client's temporary +-# tree to be sent to the server. ++# tree to be sent to the server and save it's name in the variable ++# included_name. We use a global variable instread of echoing the ++# result since the use of `include_file_or_directory` loses a trailing ++# newline. + function include_file_or_directory { + # Add a symbolic link of the named file or directory to our temporary + # directory, but only if the file or directory exists. +- local local_name=`generate_client_temp_name "$2"` +- echo "$local_name" ++ generate_client_temp_name "$2" ++ local local_name="$client_temp_name" ++ included_name="$local_name" + test -e "/$local_name" || return + + local local_dirname=`dirname "$local_name"` +@@ -431,15 +459,20 @@ function include_file_or_directory { + # function: generate_client_temp_name NAME + # + # Generate the name to be used for the given file/directory relative to the +-# client's temporary directory. ++# client's temporary directory and stores it in the variable ++# client_temp_name. We use a global variable instread of echoing the ++# result since the use of `generate_client_temp_name` loses a trailing ++# newline. + function generate_client_temp_name { + # Transform the name into a fully qualified path name +- local full_name=`echo "X$1" | sed "s,^X\\\([^/]\\\),$wd/\\\\1," | sed 's,^X,,'` ++ local full_name="$1" ++ test "${full_name:0:1}" != "/" && full_name="$wd/$full_name" + + # The same name without the initial / or trailing / +- local local_name=`echo "$full_name" | sed 's,^/\(.*\),\1,'` +- local_name=`echo "$local_name" | sed 's,\(.*\)/$,\1,'` +- echo "$local_name" ++ local local_name="${full_name:1}" ++ test "${local_name: -1:1}" = "/" && local_name="${local_name:0:$((${#local_name}-1))}" ++ ++ client_temp_name="$local_name" + } + + # function: create_request +@@ -456,7 +489,7 @@ function create_request { + fatal "Cannot create temporary directory " $tmpdir_client/script + cat > "$tmpdir_client/script/$script_file" + else +- include_file_or_directory script "$script_file" > /dev/null ++ include_file_or_directory script "$script_file" + fi + fi + +@@ -505,7 +538,7 @@ function unpack_response { + # 2) a file called stderr + # 3) a file called rc + # 4) optionally a directory named to match stap?????? +- num_files=`ls $tmpdir_server | wc -l` ++ local num_files=`ls $tmpdir_server | wc -l` + test $num_files = 4 -o $num_files = 3 || \ + fatal "Wrong number of files in server's temp directory" + test -f $tmpdir_server/stdout || \ +--- a/stap-gen-cert ++++ b/stap-gen-cert +@@ -3,7 +3,7 @@ + # Generate a certificate for the systemtap server and add it to the + # database of trusted servers for the client. + # +-# Copyright (C) 2008, 2009 Red Hat Inc. ++# Copyright (C) 2008-2010 Red Hat Inc. + # + # This file is part of systemtap, and is free software. You can + # redistribute it and/or modify it under the terms of the GNU General +@@ -14,61 +14,68 @@ + . ${PKGLIBEXECDIR}stap-env + + # Obtain the certificate database directory name. +-serverdb=$1 ++serverdb="$1" + if test "X$serverdb" = "X"; then +- serverdb=$stap_ssl_db/server ++ serverdb="$stap_ssl_db/server" + fi +-rm -fr $serverdb ++rm -fr "$serverdb" + + # Create the server's certificate database directory. +-if ! mkdir -p -m 755 $serverdb; then ++if ! mkdir -p -m 755 "$serverdb"; then + echo "Unable to create the server certificate database directory: $serverdb" >&2 + exit 1 + fi + + # Create the certificate database password file. Care must be taken + # that this file is only readable by the owner. +-if ! (touch $serverdb/pw && chmod 600 $serverdb/pw); then ++if ! (touch "$serverdb/pw" && chmod 600 "$serverdb/pw"); then + echo "Unable to create the server certificate database password file: $serverdb/pw" >&2 + exit 1 + fi + + # Generate a random password. +-mkpasswd -l 20 > $serverdb/pw 2>/dev/null || \ +-apg -a 1 -n 1 -m 20 -x 20 > $serverdb/pw 2>/dev/null || \ +-(read -n20 password $serverdb/pw) ++mkpasswd -l 20 > "$serverdb/pw" 2>/dev/null || \ ++apg -a 1 -n 1 -m 20 -x 20 > "$serverdb/pw" 2>/dev/null || \ ++(read -n20 password "$serverdb/pw") + + # Generate the server certificate database +-if ! certutil -N -d $serverdb -f $serverdb/pw > /dev/null; then ++if ! certutil -N -d "$serverdb" -f "$serverdb/pw" > /dev/null; then + echo "Unable to initialize the server certificate database directory: $serverdb" >&2 + exit 1 + fi + + # We need some random noise for generating keys +-dd bs=123 count=1 < /dev/urandom > $serverdb/noise 2> /dev/null ++dd bs=123 count=1 < /dev/urandom > "$serverdb/noise" 2> /dev/null + + # Generate a request for the server's certificate. +-certutil -R -d $serverdb -f $serverdb/pw -s "CN=Systemtap Compile Server, OU=Systemtap, O=Red Hat, C=US" -o $serverdb/stap.req -z $serverdb/noise 2> /dev/null +-rm -fr $serverdb/noise ++certutil -R -d "$serverdb" -f "$serverdb/pw" -s "CN=Systemtap Compile Server, OU=Systemtap, O=Red Hat, C=US" \ ++ -o "$serverdb/stap.req" -z "$serverdb/noise" 2> /dev/null ++rm -fr "$serverdb/noise" + + # Create the certificate file first so that it always has the proper access permissions. +-if ! (touch $serverdb/$stap_certfile && chmod 644 $serverdb/$stap_certfile); then ++if ! (touch "$serverdb/$stap_certfile" && chmod 644 "$serverdb/$stap_certfile"); then + echo "Unable to create the server certificate file: $serverdb/$stap_certfile" >&2 + exit 1 + fi + +-# Now generate the actual certificate. +-certutil -C -i $serverdb/stap.req -o $serverdb/$stap_certfile -x -d $serverdb -f $serverdb/pw -5 -8 "$HOSTNAME,localhost" >/dev/null <<-EOF ++# Now generate the actual certificate. Make is valid for 1 year. ++certutil -C -i "$serverdb/stap.req" -o "$serverdb/$stap_certfile" -x -d "$serverdb" \ ++ -f "$serverdb/pw" -v 12 -5 -8 "$HOSTNAME,localhost" >/dev/null <<-EOF + 1 + 3 + 7 + 8 + y + EOF +-rm -fr $serverdb/stap.req ++rm -fr "$serverdb/stap.req" + + # Add the certificate to the server's certificate/key database as a trusted peer, ssl server and object signer +-certutil -A -n stap-server -t "PCu,,PCu" -i $serverdb/$stap_certfile -d $serverdb -f $serverdb/pw ++certutil -A -n stap-server -t "PCu,,PCu" -i "$serverdb/$stap_certfile" -d "$serverdb" -f "$serverdb/pw" + ++# Print some information about the certificate. + echo "Certificate $serverdb/$stap_certfile created and added to database $serverdb" ++certutil -L -d "$serverdb" -n stap-server | \ ++ awk '/Validity|Not After|Not Before/ { print $0 }' | \ ++ sed 's/^ */ /' ++ + exit 0 +--- a/stap-serverd ++++ b/stap-serverd +@@ -70,12 +70,18 @@ function initialization { + -x `which ${stap_exec_prefix}stap-client 2>/dev/null`; then + ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 + fi +- elif ! test -f $stap_ssl_db/client/cert8.db; then +- # If the client's database does not exist, then initialize it with our certificate. +- # Do this only if the client has been installed. +- if test -f `which ${stap_exec_prefix}stap-client` -a \ +- -x `which ${stap_exec_prefix}stap-client`; then +- ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 ++ else ++ echo "Certificate found in database $ssl_db" >> $logfile ++ certutil -L -d "$ssl_db" -n stap-server | \ ++ awk '/Validity|Not After|Not Before/ { print $0 }' | \ ++ sed 's/^ */ /' >> $logfile ++ if ! test -f $stap_ssl_db/client/cert8.db; then ++ # If the client's database does not exist, then initialize it with our certificate. ++ # Do this only if the client has been installed. ++ if test -f `which ${stap_exec_prefix}stap-client 2>/dev/null` -a \ ++ -x `which ${stap_exec_prefix}stap-client 2>/dev/null`; then ++ ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 ++ fi + fi + fi + fi +@@ -343,11 +349,19 @@ function advertise_presence { + function listen { + # The stap-server-connect program will listen forever + # accepting requests. +- ${stap_pkglibexecdir}stap-server-connect \ +- -p $port -n $nss_cert -d $ssl_db -w $nss_pw \ +- -s "$stap_options" \ +- >> $logfile 2>&1 & +- wait '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 ++ # CVE-2009-4273 ... or at least, until resource limits fire ++ while true; do # NB: loop to avoid DoS by deliberate rlimit-induced halt ++ # NB: impose resource limits in case of mischevious data inducing ++ # too much / long computation ++ (ulimit -f 50000 -s 1000 -t 60 -u 20 -v 500000; ++ exec ${stap_pkglibexecdir}stap-server-connect \ ++ -p $port -n $nss_cert -d $ssl_db -w $nss_pw \ ++ -s "$stap_options") & ++ stap_server_connect_pid=$! ++ wait ++ # NB: avoid superfast spinning in case of a ulimit or other failure ++ sleep 1 ++ done >> $logfile 2>&1 + } + + # function: warning [ MESSAGE ] +@@ -379,8 +393,8 @@ function terminate { + wait '%avahi-publish-service' >> $logfile 2>&1 + + # Kill any running 'stap-server-connect' job. +- kill -s SIGTERM '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 +- wait '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 ++ kill -s SIGTERM $stap_server_connect_pid >> $logfile 2>&1 ++ wait $stap_server_connect_pid >> $logfile 2>&1 + + exit + } +--- a/testsuite/systemtap.server/client_args.exp ++++ b/testsuite/systemtap.server/client_args.exp +@@ -5,33 +5,34 @@ set test "Invalid Server Client Argument + set test_file $srcdir/systemtap.server/test.stp + + # Test invalid combinations. +-set error_regexp ".*You can't specify .* when --unprivileged is specified.*" ++set error_regexp ".*(ERROR)|(You can't specify .* when --unprivileged is specified).*" + + set invalid_options [list \ +- "--unprivileged --client-options -a i386" \ + "--unprivileged --client-options -B X=Y" \ + "--unprivileged --client-options -D X=Y" \ + "--unprivileged --client-options -I /tmp" \ + "--unprivileged --client-options -m test" \ + "--unprivileged --client-options -R /tmp" \ +- "--unprivileged --client-options -r [exec uname -r]" \ +- "--unprivileged --client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ +- "--client-options --unprivileged -a i386" \ ++ "--unprivileged --client-options -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ + "--client-options --unprivileged -B X=Y" \ + "--client-options --unprivileged -D X=Y" \ + "--client-options --unprivileged -I /tmp" \ + "--client-options --unprivileged -m test" \ + "--client-options --unprivileged -R /tmp" \ +- "--client-options --unprivileged -r [exec uname -r]" \ +- "--client-options --unprivileged -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ +- "--client-options -a i386 --unprivileged" \ ++ "--client-options --unprivileged -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ + "--client-options -B X=Y --unprivileged" \ + "--client-options -D X=Y --unprivileged" \ + "--client-options -I /tmp --unprivileged" \ + "--client-options -m test --unprivileged" \ + "--client-options -R /tmp --unprivileged" \ +- "--client-options -r [exec uname -r] --unprivileged" \ +- "--client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r] --unprivileged" \ ++ "--client-options -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r] --unprivileged" \ ++ "--client-options -R /path" \ ++ "-D \"foo;bar\"" \ ++ "-D 2=4" \ ++ "-D \"foo;bar\"" \ ++ "--client-options -r /path" \ ++ "-S /path" \ ++ "--client-options -q" \ + ] + + foreach options $invalid_options { +@@ -66,9 +67,8 @@ set valid_options [list \ + "-D X=Y" \ + "-I /tmp" \ + "-m test" \ +- "-R /tmp" \ + "-r [exec uname -r]" \ +- "-a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ ++ "-a i386 -B X=Y -D X=Y -I /tmp -m test -r [exec uname -r]" \ + "--unprivileged" \ + "--unprivileged -a i386" \ + "--unprivileged -B X=Y" \ +@@ -80,13 +80,11 @@ set valid_options [list \ + "--unprivileged -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ + "--client-options" \ + "--client-options -a i386" \ +- "--client-options -B X=Y" \ + "--client-options -D X=Y" \ + "--client-options -I /tmp" \ + "--client-options -m test" \ +- "--client-options -R /tmp" \ + "--client-options -r [exec uname -r]" \ +- "--client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ ++ "--client-options -a i386 -D X=Y -I /tmp -m test -r [exec uname -r]" \ + "--unprivileged --client-options" \ + "--client-options --unprivileged" \ + "--unprivileged -a i386 --client-options" \ +--- a/testsuite/systemtap.server/hello.stp ++++ b/testsuite/systemtap.server/hello.stp +@@ -1,4 +1,4 @@ +-#! stap ++#! stap -p5 + + probe begin + { +--- a/testsuite/systemtap.server/server_args.exp ++++ b/testsuite/systemtap.server/server_args.exp +@@ -40,11 +40,13 @@ proc stap_direct_and_with_client {stap s + # Some messages contain the names of files or directories + # and will be prefixed for the client. + if {[regexp "^ (.*)" $expected_line match data]} { +- if {[regexp "^ tapsets/.*/$data" $line]} { ++ # Special characters in the regexp need to be quoted. ++ regsub -all "\[\"\\\\;\*\]" $data {\\\0} data ++ if {[regexp "^ tapsets.*/$data" $line]} { + incr n + continue + } +- if {[regexp "^ runtime/.*/$data" $line]} { ++ if {[regexp "^ runtime.*/$data" $line]} { + incr n + continue + } +@@ -57,7 +59,9 @@ proc stap_direct_and_with_client {stap s + } + } else { + if {[regexp "^Input file '(.*)' is empty or missing." $expected_line match data]} { +- if {[regexp "^Input file 'script/.*/$data' is empty or missing." $line]} { ++ # Special characters in the regexp need to be quoted. ++ regsub -all "\[\"\\\\;\*\]" $data {\\\0} data ++ if {[regexp "^Input file 'script.*/$data' is empty or missing." $line]} { + incr n + continue + } +@@ -110,21 +114,27 @@ if {[installtest_p]} then { + # for debugging a currently failing case and helps to ensure that previously + # fixed cases do not regress. + set previously_fixed [list \ ++ "-p1 -I=\\w94\nbh -e -Dhfuo0iu7 -c" \ ++ "-p1 -I8o\\2ie -e'1\\ -D\n\" -c" \ ++ "-p1 -Ira\\3;c g -e0fle'qq -Dr/316k\\o8 -cjyoc\n3" \ ++ "-p1 -I6p3 -elc -Dqgsgv' -c" \ ++ "-p1 -I\"vyv;z -ej\"/3 -D/ 01qck\n -c3u55zut" \ ++ "-p1 -I1 -eo9e\nx047q -D9xyefk0a -cvl98/x1'i" \ + "-p1 -c; test.stp" \ +- "-p1 -I4hgy96 -R -e5oo39p -Bile\\vp -Ddx8v -c4;" \ +- "-p1 -I -Repwd9 -esq3wors -Btmk;\\t -Dz -c*eibz8h2e" \ +- "-p1 -I -Ry a -em339db5 -B;ae41428d -Du2;c0ps -ch9o\\" \ +- "-p1 -Ipfjps4 -Rx479 -ebug4dc -Bih;fe2 -Du8vd fvkl -c" \ +- "-p1 -I0\"nspzjyf -R -e5r3up8h -Bgqnyjq6w -Dmi;ojp9m -cx;a2fat" \ +- "-p1 -Iu -R9 -ek7;r -Big -Dcu\"; -c\"hc" \ +- "-p1 -Icd4fidq -Rkj m40mv -edn -B7ria -D;8ha\\cjr -c1*vnq" \ +- "-p1 -I;3 -R3lq;vp -er8e -Bgdqjqdy -D -cb6k29z" \ +- "-p1 -Ircj -R -e -B -D -c\\vmww" \ +- "-p1 -Illc5 -Rug*\\o -e65wof9 -B qr*=x7x5 -D -cgx;" \ +- "-p1 -Iyaj420=3 -R -e\" -Bx68j -D -cd'5mi" \ +- "-p1 -Ir -Rwd8;;sjl -e -Bxh; -D29\\ -cj2szt;4" \ +- "-p1 -Ibno3=b4sk -R*5 -e' -Byl63flos -Dg2-j;e -c2ijx'" \ +- "-p1 -I285v7pl -R9a -eo5\\0 -Bfs* -D86s -c-c*v" \ ++ "-p1 -I4hgy96 -e5oo39p -Ddx8v -c4;" \ ++ "-p1 -I -esq3wors -Dz -c*eibz8h2e" \ ++ "-p1 -I a -em339db5 -Du2;c0ps -ch9o\\" \ ++ "-p1 -Ipfjps4 -ebug4dc -Du8vd fvkl -c" \ ++ "-p1 -I0\"nspzjyf -e5r3up8h -Dmi;ojp9m -cx;a2fat" \ ++ "-p1 -Iu -ek7;r -Dcu\"; -c\"hc" \ ++ "-p1 -Icd4fidq m40mv -edn -D;8ha\\cjr -c1*vnq" \ ++ "-p1 -I;3 -er8e -D -cb6k29z" \ ++ "-p1 -Ircj -e -D -c\\vmww" \ ++ "-p1 -Illc5 -e65wof9 qr*=x7x5 -D -cgx;" \ ++ "-p1 -Iyaj420=3 -e\" -D -cd'5mi" \ ++ "-p1 -Ir -e -D29\\ -cj2szt;4" \ ++ "-p1 -Ibno3=b4sk -e' -Dg2-j;e -c2ijx'" \ ++ "-p1 -I285v7pl -eo5\\0 -D86s -c-c*v" \ + ] + + set i 0 +@@ -140,7 +150,10 @@ foreach options $previously_fixed { + # Generate semi-random arguments containing with potential problem characters. + # Check that running systemtap with the client/server generates output + # comparable to running stap directly. +-set dangerous_options [list "-I" "-R" "-e" "-B" "-D" "-c"] ++set dangerous_options [list "-I" "-e" "-D" "-c" "-S"] ++# NB: Other options could be candidates here, like -r and -B, but ++# there stap-server imposes more restrictions than local stap, so ++# this simple error-matching test cannot use them. + set argchars "0123456789/;*'=-\\\"\n abcdefghijklmnopqrstuvwxyz" + + for {set i 0} {$i < $iterations} {incr i} { +--- a/util.cxx ++++ b/util.cxx +@@ -1,5 +1,5 @@ + // Copyright (C) Andrew Tridgell 2002 (original file) +-// Copyright (C) 2006, 2009 Red Hat Inc. (systemtap changes) ++// Copyright (C) 2006-2010 Red Hat Inc. (systemtap changes) + // + // This program is free software; you can redistribute it and/or + // modify it under the terms of the GNU General Public License as +@@ -19,6 +19,8 @@ + #include "sys/sdt.h" + #include + #include ++#include ++#include + + extern "C" { + #include +@@ -31,6 +33,7 @@ extern "C" { + #include + #include + #include ++#include + } + + using namespace std; +@@ -413,4 +416,35 @@ kill_stap_spawn(int sig) + return spawned_pid ? kill(spawned_pid, sig) : 0; + } + ++ ++void assert_regexp_match (const string& name, const string& value, const string& re) ++{ ++ typedef map cache; ++ static cache compiled; ++ cache::iterator it = compiled.find (re); ++ regex_t* r = 0; ++ if (it == compiled.end()) ++ { ++ r = new regex_t; ++ int rc = regcomp (r, re.c_str(), REG_ICASE|REG_NOSUB|REG_EXTENDED); ++ if (rc) { ++ cerr << "regcomp " << re << " (" << name << ") error rc=" << rc << endl; ++ exit(1); ++ } ++ compiled[re] = r; ++ } ++ else ++ r = it->second; ++ ++ // run regexec ++ int rc = regexec (r, value.c_str(), 0, 0, 0); ++ if (rc) ++ { ++ cerr << "ERROR: Safety pattern mismatch for " << name ++ << " ('" << value << "' vs. '" << re << "') rc=" << rc << endl; ++ exit(1); ++ } ++} ++ ++ + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ +--- a/util.h ++++ b/util.h +@@ -21,7 +21,7 @@ const std::string cmdstr_quoted(const st + std::string git_revision(const std::string& path); + int stap_system(int verbose, const std::string& command); + int kill_stap_spawn(int sig); +- ++void assert_regexp_match (const std::string& name, const std::string& value, const std::string& re); + + // stringification generics + diff --git a/systemtap-CVE-2010-0411.diff b/systemtap-CVE-2010-0411.diff new file mode 100644 index 0000000..59cf89a --- /dev/null +++ b/systemtap-CVE-2010-0411.diff @@ -0,0 +1,187 @@ +Subject: VUL-1: systemtap: DoS issue in __get_argv() function +References: bnc#577382 +Signed-Off-By: Tony Jones + +commit a2d399c87a642190f08ede63dc6fc434a5a8363a +Author: Josh Stone +Date: Thu Feb 4 17:47:31 2010 -0800 + + PR11234: Rewrite __get_argv without embedded-C + + We now implement __get_argv's string building in pure stap script. + Also, every argument is now quoted, which is different than before, but + it's much more robust about handling special characters. + +diff --git a/tapset/aux_syscalls.stp b/tapset/aux_syscalls.stp +index bab0f64..e762b37 100644 +--- a/tapset/aux_syscalls.stp ++++ b/tapset/aux_syscalls.stp +@@ -399,124 +399,53 @@ function __sem_flags:string(semflg:long) + + + /* This function copies an argv from userspace. */ +-function __get_argv:string(a:long, first:long) +-%{ /* pure */ +- char __user *__user *argv = (char __user *__user *)(long)THIS->a; +- char __user *vstr; +- int space, rc, len = MAXSTRINGLEN; +- char *str = THIS->__retvalue; +- char buf[80]; +- char *ptr = buf; +- +- +- if (THIS->first && argv) +- argv++; +- +- while (argv != NULL) { +- if (__stp_get_user (vstr, argv)) +- break; +- +- if (vstr == NULL) +- break; +- +- rc = _stp_strncpy_from_user(buf, vstr, 79); +- if (rc <= 0) +- break; +- +- /* check for whitespace in string */ +- buf[rc] = 0; +- ptr = buf; +- space = 0; +- while (*ptr && rc--) { +- if (isspace(*ptr++)) { +- space = 1; +- break; +- } +- } +- +- if (len != MAXSTRINGLEN && len) { +- *str++=' '; +- len--; +- } +- +- if (space && len) { +- *str++='\"'; +- len--; +- } +- +- rc = strlcpy (str, buf, len); +- str += rc; +- len -= rc; +- +- if (space && len) { +- *str++='\"'; +- len--; +- } +- +- argv++; ++function __get_argv:string(argv:long, first:long) ++{ ++%( CONFIG_64BIT == "y" %? ++ if (first && argv) ++ argv += 8 ++ while (argv) { ++ vstr = user_long(argv) ++ if (!vstr) ++ break ++ if (len) ++ str .= " " ++ str .= user_string_quoted(vstr) ++ ++ newlen = strlen(str) ++ if (newlen == len) ++ break ++ len = newlen ++ argv += 8 + } +- *str = 0; +-%} +-/* This function copies an argv from userspace. */ +-function __get_compat_argv:string(a:long, first:long) +-%{ /* pure */ +-#ifdef CONFIG_COMPAT +- compat_uptr_t __user *__user *argv = (compat_uptr_t __user *__user *)(long)THIS->a; +- compat_uptr_t __user *vstr; +- int space, rc, len = MAXSTRINGLEN; +- char *str = THIS->__retvalue; +- char buf[80]; +- char *ptr = buf; +- +- if (THIS->first && argv) +- argv++; +- +- while (argv != NULL) { +- if (__stp_get_user (vstr, argv)) +- break; +- +- if (vstr == NULL) +- break; +- +- rc = _stp_strncpy_from_user(buf, (char *)vstr, 79); +- if (rc <= 0) +- break; +- +- /* check for whitespace in string */ +- buf[rc] = 0; +- ptr = buf; +- space = 0; +- while (*ptr && rc--) { +- if (isspace(*ptr++)) { +- space = 1; +- break; +- } +- } +- +- if (len != MAXSTRINGLEN && len) { +- *str++=' '; +- len--; +- } +- +- if (space && len) { +- *str++='\"'; +- len--; +- } +- +- rc = strlcpy (str, buf, len); +- str += rc; +- len -= rc; +- +- if (space && len) { +- *str++='\"'; +- len--; +- } + +- argv++; ++ return str ++%: ++ return __get_compat_argv(argv, first) ++%) ++} ++/* This function copies an argv from userspace. */ ++function __get_compat_argv:string(argv:long, first:long) ++{ ++ if (first && argv) ++ argv += 4 ++ while (argv) { ++ vstr = user_int(argv) & 0xffffffff ++ if (!vstr) ++ break ++ if (len) ++ str .= " " ++ str .= user_string_quoted(vstr) ++ ++ newlen = strlen(str) ++ if (newlen == len) ++ break ++ len = newlen ++ argv += 4 + } +- *str = 0; +-#endif +-%} ++ ++ return str ++} + + /* + * Return the symbolic string representation diff --git a/systemtap-CVE-limit-dwarf-expression-stack-size.patch b/systemtap-CVE-limit-dwarf-expression-stack-size.patch deleted file mode 100644 index 4394e4f..0000000 --- a/systemtap-CVE-limit-dwarf-expression-stack-size.patch +++ /dev/null @@ -1,135 +0,0 @@ -From: Jan Lieskovsky -Subject: Three SystemTap-1.0 denial of service issues -References: CVE-2009-2911, BNC#548361 -Upstream: yes - - Three denial of service flaws were found in the SystemTap -instrumentation system of version 1.0, when the --unprivileged mode was -activated: - -b, Kernel stack frame overflow allows local attackers to cause denial -of service via specially-crafted user-provided DWARF information. - -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/systemtap-CVE-limit-printf-arguments.patch b/systemtap-CVE-limit-printf-arguments.patch deleted file mode 100644 index 32041a0..0000000 --- a/systemtap-CVE-limit-printf-arguments.patch +++ /dev/null @@ -1,75 +0,0 @@ -From: Jan Lieskovsky -Subject: Three SystemTap-1.0 denial of service issues -References: CVE-2009-2911, BNC#548361 -Upstream: yes - - Three denial of service flaws were found in the SystemTap -instrumentation system of version 1.0, when the --unprivileged mode was -activated: - -a, Kernel stack overflow allows local attackers to cause denial of service or -execute arbitrary code via long number of parameters, provided to the print* -call. - -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 tmp; - - diff --git a/systemtap-CVE-unwind-table-size-checks.patch b/systemtap-CVE-unwind-table-size-checks.patch deleted file mode 100644 index 408239b..0000000 --- a/systemtap-CVE-unwind-table-size-checks.patch +++ /dev/null @@ -1,193 +0,0 @@ -From: Jan Lieskovsky -Subject: Three SystemTap-1.0 denial of service issues -References: CVE-2009-2911, BNC#548361 -Upstream: yes - - Three denial of service flaws were found in the SystemTap -instrumentation system of version 1.0, when the --unprivileged mode was -activated: - -c, Absent check(s) for the upper bound of the size of the unwind table - and for the upper bound of the size of each of the CIE/CFI records, could - allow an attacker to cause a denial of service (infinite loop). - -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 != ¬_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 == ¬_fde || (ptrType = fde_pointer_type(cie)) < 0) -+ if (cie == NULL || cie == ¬_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 - } - -+// 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/systemtap-docdir-fix.diff b/systemtap-docdir-fix.diff index 9cb4ad9..ecdced0 100644 --- a/systemtap-docdir-fix.diff +++ b/systemtap-docdir-fix.diff @@ -1,3 +1,10 @@ +From: Tony Jones +Subject: change doc install path +References: none +Upstream: never + +SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. + --- Makefile.am | 2 +- doc/Makefile.am | 2 +- @@ -7,15 +14,15 @@ --- a/Makefile.am +++ b/Makefile.am -@@ -218,7 +218,7 @@ +@@ -257,7 +257,7 @@ install-data-local: | while read f; do if test -x $$f; then \ i_cmd="$(INSTALL_PROGRAM)"; else \ i_cmd="$(INSTALL_DATA)"; fi; \ - $$i_cmd -D $$f $(DESTDIR)$(docdir)/examples/$$f; done) + $$i_cmd -D $$f $(DESTDIR)$(datadir)/doc/packages/systemtap/examples/$$f; done) test -e $(DESTDIR)$(sysconfdir)/systemtap || mkdir -p $(DESTDIR)$(sysconfdir)/systemtap - - TEST_COV_DIR = coverage + if BUILD_SERVER + test -e $(DESTDIR)$(localstatedir)/run/stap-server || mkdir -p $(DESTDIR)$(localstatedir)/run/stap-server --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -2,7 +2,7 @@ @@ -24,7 +31,7 @@ PDF_FILES = tutorial.pdf langref.pdf -DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap +DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/packages/systemtap - SUBDIRS = SystemTap_Tapset_Reference + SUBDIRS = SystemTap_Tapset_Reference beginners if BUILD_DOCS --- a/doc/SystemTap_Tapset_Reference/Makefile.am @@ -43,7 +50,7 @@ ### --- a/stapex.3stap.in +++ b/stapex.3stap.in -@@ -114,12 +114,12 @@ +@@ -114,12 +114,12 @@ To list the probeable functions and loca .SH MORE EXAMPLES Larger examples, demos and samples can be found in diff --git a/systemtap-docs.changes b/systemtap-docs.changes index 8573048..1a076e3 100644 --- a/systemtap-docs.changes +++ b/systemtap-docs.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Thu Mar 11 22:49:52 UTC 2010 - tonyj@novell.com + +- Update to version 1.1. See systemtap.changes for full changelog. + ------------------------------------------------------------------- Wed Dec 2 23:52:10 UTC 2009 - tonyj@novell.com diff --git a/systemtap-docs.spec b/systemtap-docs.spec index 35adc8f..04b348f 100644 --- a/systemtap-docs.spec +++ b/systemtap-docs.spec @@ -1,5 +1,5 @@ # -# spec file for package systemtap-docs (Version 1.0) +# spec file for package systemtap-docs (Version 1.1) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -22,13 +22,11 @@ Name: systemtap-docs BuildRequires: gcc-c++ libebl-devel pkg-config # for documents BuildRequires: xmlto -%if %suse_version > 1030 BuildRequires: fop BuildRequires: latex2html -%endif %define use_snapshot 0 License: GPLv2+ -Version: 1.0 +Version: 1.1 Release: 1 Summary: Documents and examples for systemtap Group: Development/Tools/Debuggers @@ -39,7 +37,7 @@ Url: http://sourceware.org/systemtap/ %define package_version %{version} %endif Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 -Patch: systemtap-docdir-fix.diff +Patch1: systemtap-docdir-fix.diff Patch2: systemtap-xmlto-fop.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch @@ -63,10 +61,8 @@ Authors: %else %setup -n systemtap-%{package_version} -q %endif -%patch -p1 -%if %suse_version > 1030 +%patch1 -p1 %patch2 -p1 -%endif %build autoreconf -fi @@ -74,12 +70,9 @@ autoreconf -fi make %{?jobs:-j %jobs} %install -%if %suse_version < 1030 -# workaround for old autoconf -export MKDIR_P="mkdir -p" -%endif %makeinstall doc -cp README AUTHORS NEWS COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ +# COPYING packaged by main spec +cp README AUTHORS NEWS $RPM_BUILD_ROOT%{_docdir}/systemtap/ # remove binaries and runtime stuff rm -rf $RPM_BUILD_ROOT%{_bindir} rm -rf $RPM_BUILD_ROOT%{_libexecdir} diff --git a/systemtap-ioblock-suse-kernel-fix.diff b/systemtap-ioblock-suse-kernel-fix.diff index e274cd6..3f12a69 100644 --- a/systemtap-ioblock-suse-kernel-fix.diff +++ b/systemtap-ioblock-suse-kernel-fix.diff @@ -1,6 +1,10 @@ ---- a/tapset/ioblock.stp-dist 2008-12-05 08:14:19.000000000 +0100 -+++ b/tapset/ioblock.stp 2008-12-05 08:14:27.000000000 +0100 -@@ -122,7 +122,7 @@ +--- + tapset/ioblock.stp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/tapset/ioblock.stp ++++ b/tapset/ioblock.stp +@@ -118,7 +118,7 @@ probe ioblock.request = kernel.function vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments @@ -9,7 +13,7 @@ hw_segments = $bio->bi_hw_segments %) size = $bio->bi_size -@@ -178,7 +178,7 @@ +@@ -169,7 +169,7 @@ probe ioblock.end = kernel.function("bio vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments diff --git a/systemtap-prevent-nested-arg.diff b/systemtap-prevent-nested-arg.diff new file mode 100644 index 0000000..8633db2 --- /dev/null +++ b/systemtap-prevent-nested-arg.diff @@ -0,0 +1,182 @@ +From: Josh Stone +Date: Tue Jan 19 15:36:35 2010 -0800 +Git-Repo: git://sources.redhat.com/git/systemtap.git +Git-Commit: 9300f661214a4f4dfac75878485867b30c7db389 +Signed-Off-By: Tony Jones + + tonyj: this fixes parse errors such as: + parse error: expected 'probe', 'global', 'function', or '%{' + saw: identifier '?robe' at + + ------------------------------------------------- + PR11195: Prevent all nested argument substitution + + Our existing protection only made sure that the first token in a + substitution wasn't a nested substitution. That's not sufficient when + there could be multiple tokens involved. This patch makes sure that no + nested tokens are ever allowed to be argument substitutions. + + This also adds a cursor_suspended_line/column and resets the main + cursor_line/column to the beginning of the substitution, so errors will + point a little closer to the right place. + +diff --git a/parse.cxx b/parse.cxx +index edb1927..2688d6d 100644 +--- a/parse.cxx ++++ b/parse.cxx +@@ -632,7 +632,8 @@ parser::peek_kw (std::string const & kw) + + lexer::lexer (istream& input, const string& in, systemtap_session& s): + input_name (in), input_pointer (0), input_end (0), +- cursor_suspend_count(0), cursor_line (1), cursor_column (1), ++ cursor_suspend_count(0), cursor_suspend_line (1), cursor_suspend_column (1), ++ cursor_line (1), cursor_column (1), + session(s), current_file (0) + { + getline(input, input_contents, '\0'); +@@ -693,9 +694,15 @@ lexer::input_get () + ++input_pointer; + + if (cursor_suspend_count) +- // Track effect of input_put: preserve previous cursor/line_column +- // until all of its characters are consumed. +- cursor_suspend_count --; ++ { ++ // Track effect of input_put: preserve previous cursor/line_column ++ // until all of its characters are consumed. ++ if (--cursor_suspend_count == 0) ++ { ++ cursor_line = cursor_suspend_line; ++ cursor_column = cursor_suspend_column; ++ } ++ } + else + { + // update source cursor +@@ -714,12 +721,16 @@ lexer::input_get () + + + void +-lexer::input_put (const string& chars) ++lexer::input_put (const string& chars, const token* t) + { + size_t pos = input_pointer - input_contents.data(); + // clog << "[put:" << chars << " @" << pos << "]"; + input_contents.insert (pos, chars); + cursor_suspend_count += chars.size(); ++ cursor_suspend_line = cursor_line; ++ cursor_suspend_column = cursor_column; ++ cursor_line = t->location.line; ++ cursor_column = t->location.column; + input_pointer = input_contents.data() + pos; + input_end = input_contents.data() + input_contents.size(); + } +@@ -731,19 +742,11 @@ lexer::scan (bool wildcard) + token* n = new token; + n->location.file = current_file; + +- unsigned semiskipped_p = 0; +- +- skip: ++skip: ++ bool suspended = (cursor_suspend_count > 0); + n->location.line = cursor_line; + n->location.column = cursor_column; + +- semiskip: +- if (semiskipped_p > 1) +- { +- input_get (); +- throw parse_error ("invalid nested substitution of command line arguments"); +- } +- + int c = input_get(); + // clog << "{" << (char)c << (char)c2 << "}"; + if (c < 0) +@@ -762,38 +765,41 @@ lexer::scan (bool wildcard) + // characters; @1..@999 are quoted/escaped as strings. + // $# and @# expand to the number of arguments, similarly + // raw or quoted. +- if ((c == '$' || c == '@') && +- (c2 == '#')) ++ if ((c == '$' || c == '@') && (c2 == '#')) + { ++ n->content.push_back (c); ++ n->content.push_back (c2); + input_get(); // swallow '#' +- stringstream converter; +- converter << session.args.size (); +- if (c == '$') input_put (converter.str()); +- else input_put (lex_cast_qstring (converter.str())); +- semiskipped_p ++; +- goto semiskip; ++ if (suspended) ++ throw parse_error ("invalid nested substitution of command line arguments", n); ++ size_t num_args = session.args.size (); ++ input_put ((c == '$') ? lex_cast (num_args) : lex_cast_qstring (num_args), n); ++ n->content.clear(); ++ goto skip; + } +- else if ((c == '$' || c == '@') && +- (isdigit (c2))) ++ else if ((c == '$' || c == '@') && (isdigit (c2))) + { ++ n->content.push_back (c); + unsigned idx = 0; + do + { + input_get (); + idx = (idx * 10) + (c2 - '0'); ++ n->content.push_back (c2); + c2 = input_peek (); + } while (c2 > 0 && + isdigit (c2) && + idx <= session.args.size()); // prevent overflow ++ if (suspended) ++ throw parse_error ("invalid nested substitution of command line arguments", n); + if (idx == 0 || + idx-1 >= session.args.size()) + throw parse_error ("command line argument index " + lex_cast(idx) + + " out of range [1-" + lex_cast(session.args.size()) + "]", n); +- string arg = session.args[idx-1]; +- if (c == '$') input_put (arg); +- else input_put (lex_cast_qstring (arg)); +- semiskipped_p ++; +- goto semiskip; ++ const string& arg = session.args[idx-1]; ++ input_put ((c == '$') ? arg : lex_cast_qstring (arg), n); ++ n->content.clear(); ++ goto skip; + } + + else if (isalpha (c) || c == '$' || c == '@' || c == '_' || +diff --git a/parse.h b/parse.h +index 5587586..0ff8664 100644 +--- a/parse.h ++++ b/parse.h +@@ -79,12 +79,14 @@ public: + private: + inline int input_get (); + inline int input_peek (unsigned n=0); +- void input_put (const std::string&); ++ void input_put (const std::string&, const token*); + std::string input_name; + std::string input_contents; + const char *input_pointer; // index into input_contents + const char *input_end; + unsigned cursor_suspend_count; ++ unsigned cursor_suspend_line; ++ unsigned cursor_suspend_column; + unsigned cursor_line; + unsigned cursor_column; + systemtap_session& session; +diff --git a/testsuite/parseko/preprocess16.stp b/testsuite/parseko/preprocess16.stp +new file mode 100755 +index 0000000..364bad6 +--- /dev/null ++++ b/testsuite/parseko/preprocess16.stp +@@ -0,0 +1,4 @@ ++#! /bin/sh ++ ++# recursive after the first token (PR11195) ++stap -p1 -e 'probe begin {$1}' 'x $1' diff --git a/systemtap-xmlto-fop.diff b/systemtap-xmlto-fop.diff index 033f8fb..3558809 100644 --- a/systemtap-xmlto-fop.diff +++ b/systemtap-xmlto-fop.diff @@ -4,14 +4,14 @@ --- a/doc/SystemTap_Tapset_Reference/Makefile.am +++ b/doc/SystemTap_Tapset_Reference/Makefile.am -@@ -34,7 +34,9 @@ +@@ -43,7 +43,9 @@ stamp-htmldocs: tapsets.xml # bump up the allocated space so "xmlto pdf" works tapsets.pdf: tapsets.xml -- env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml -+# env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml +- env pool_size=2000000 hash_extra=2000000 xmlto $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 ++# env pool_size=2000000 hash_extra=2000000 xmlto $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 + xmlto fo tapsets.xml + fop tapsets.fo tapsets.pdf stamp-mandocs: tapsets.xml - xmlto man -o man3 tapsets.xml + xmlto $(XMLTOMANPARAMS) man -o man3 tapsets.xml >/dev/null 2>&1 diff --git a/systemtap.changes b/systemtap.changes index 94c39a9..e1bf13e 100644 --- a/systemtap.changes +++ b/systemtap.changes @@ -1,3 +1,16 @@ +------------------------------------------------------------------- +Thu Mar 11 23:56:17 UTC 2010 - tonyj@novell.com + +- Add dependancies for systemtap shell scripts (coreutils, zip, avahi) + +------------------------------------------------------------------- +Thu Mar 11 22:47:15 UTC 2010 - tonyj@novell.com + +- Update to version 1.1 +- Fixes for CVE-2009-4273 (second part, also known as CVE-2010-0412) and + CVE-2010-0411. +- Fix parsing error (systemtap-prevent-nested-arg.diff) + ------------------------------------------------------------------- Wed Dec 2 23:51:24 UTC 2009 - tonyj@novell.com diff --git a/systemtap.spec b/systemtap.spec index 013bca5..d5ad021 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -1,5 +1,5 @@ # -# spec file for package systemtap (Version 1.0) +# spec file for package systemtap (Version 1.1) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -23,7 +23,7 @@ BuildRequires: gcc-c++ glib2-devel libcap-devel libebl-devel pkg-config sqlite- BuildRequires: mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools %define use_snapshot 0 License: GPLv2+ -Version: 1.0 +Version: 1.1 Release: 1 Summary: Instrumentation System Group: Development/Tools/Debuggers @@ -35,12 +35,15 @@ Url: http://sourceware.org/systemtap/ %else %define package_version %{version} %endif -Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 -Patch: systemtap-docdir-fix.diff -Patch2: systemtap-ioblock-suse-kernel-fix.diff -Patch3: systemtap-CVE-limit-dwarf-expression-stack-size.patch -Patch4: systemtap-CVE-limit-printf-arguments.patch -Patch5: systemtap-CVE-unwind-table-size-checks.patch +Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 +# need -docdir patch even though docs are packaged by systemtap-docs.spec +# so that they are installed into directories matching below rm -rf's +Patch1: systemtap-docdir-fix.diff +Patch2: systemtap-ioblock-suse-kernel-fix.diff +Patch3: systemtap-CVE-2009-4273.diff +Patch4: systemtap-CVE-2010-0411.diff +Patch5: systemtap-prevent-nested-arg.diff + Requires: libebl1 Requires: %{name}-runtime = %{version}-%{release} BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -82,6 +85,8 @@ License: GPLv2+ Group: Development/Tools/Debuggers Summary: Systemtap client Requires: %{name}-runtime = %{version}-%{release} +# dependancies for systemtap shell scripts +Requires: coreutils avahi avahi-utils mozilla-nss-tools zip unzip %description client SystemTap is an instrumentation system for systems running Linux 2.6. @@ -101,6 +106,8 @@ License: GPLv2+ Group: Development/Tools/Debuggers Summary: Systemtap server Requires: %{name} = %{version}-%{release} +# dependancies for systemtap shell scripts +Requires: coreutils avahi avahi-utils mozilla-nss-tools zip unzip %description server SystemTap is an instrumentation system for systems running Linux 2.6. @@ -140,7 +147,7 @@ Authors: %else %setup -n %{name}-%{package_version} -q %endif -%patch -p1 +%patch1 -p1 %patch2 -p1 %patch3 -p1 %patch4 -p1 @@ -152,16 +159,19 @@ autoreconf -fi make %{?jobs:-j %jobs} %install -%if %suse_version < 1030 -# workaround for old autoconf -export MKDIR_P="mkdir -p" -%endif %makeinstall -mkdir -p $RPM_BUILD_ROOT/var/cache/systemtap -# doc subpackage is built separetely -# cp README AUTHORS NEWS COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ -rm -rf $RPM_BUILD_ROOT%{_docdir}/systemtap +# XXX +rm -f $RPM_BUILD_ROOT/usr/lib/systemtap/stap-server-request +# README, AUTHORS, NEWS, man3 and all examples packaged by systemtap-docs +# COPYING needs to stay in main for GPL +rm -rf $RPM_BUILD_ROOT%{_docdir}/systemtap/ rm -rf $RPM_BUILD_ROOT%{_mandir}/man3 +mkdir -p $RPM_BUILD_ROOT%{_docdir}/systemtap/ +cp COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ +mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/cache/systemtap +mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/systemtap +mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/log +touch $RPM_BUILD_ROOT%{_localstatedir}/log/stap-server.log %clean rm -rf ${RPM_BUILD_ROOT} @@ -170,37 +180,51 @@ rm -rf ${RPM_BUILD_ROOT} %defattr(-,root,root) %{_bindir}/stap %{_mandir}/man1/* -%{_datadir}/systemtap -%dir %attr(0755,root,root) /var/cache/systemtap +%dir %{_datadir}/%{name} +%{_datadir}/%{name}/runtime +%{_datadir}/%{name}/tapset +#packaged by systemtap-initscript in upstream +%dir %{_localstatedir}/cache/systemtap +%dir %{_localstatedir}/run/systemtap %files runtime %defattr(-,root,root) +%doc %{_docdir}/systemtap %{_bindir}/staprun %{_bindir}/stap-report -%{_libexecdir}/systemtap -%{_mandir}/man8/staprun.* +%{_bindir}/stap-authorize-signing-cert +%dir %{_libexecdir}/%{name} +%{_libexecdir}/%{name}/stapio +%{_libexecdir}/%{name}/stap-env +%{_libexecdir}/%{name}/stap-authorize-cert +%{_mandir}/man8/staprun.8* +%{_mandir}/man8/stap-authorize-signing-cert.8* %files client %defattr(-,root,root) +%defattr(-,root,root) %{_bindir}/stap-client -%{_bindir}/stap-find-servers -%{_bindir}/stap-find-or-start-server -%{_bindir}/stap-start-server -%{_bindir}/stap-client-connect -%{_bindir}/stap-env +%{_bindir}/stap-authorize-server-cert +%{_libexecdir}/%{name}/stap-find-servers +%{_libexecdir}/%{name}/stap-client-connect +%{_mandir}/man8/stap-client.8* +%{_mandir}/man8/stap-authorize-server-cert.8* %files server %defattr(-,root,root) +%{_bindir}/stap-authorize-server-cert %{_bindir}/stap-server -%{_bindir}/stap-serverd -%{_bindir}/stap-start-server -%{_bindir}/stap-stop-server -%{_bindir}/stap-server-connect -%{_bindir}/stap-authorize* -%{_bindir}/stap-env -%{_bindir}/stap-gen-cert -%{_bindir}/stap-sign-module -%{_mandir}/man8/stap-server.* +%{_libexecdir}/%{name}/stap-serverd +%{_libexecdir}/%{name}/stap-start-server +%{_libexecdir}/%{name}/stap-find-servers +%{_libexecdir}/%{name}/stap-find-or-start-server +%{_libexecdir}/%{name}/stap-stop-server +%{_libexecdir}/%{name}/stap-gen-cert +%{_libexecdir}/%{name}/stap-server-connect +%{_libexecdir}/%{name}/stap-sign-module +%{_mandir}/man8/stap-server.8* +%{_mandir}/man8/stap-authorize-server-cert.8* +%ghost %{_localstatedir}/log/stap-server.log %files sdt-devel %defattr(-,root,root) From b8cefb4b4d4f0146bfdc5d06221a5e4c2a3eec4a37cbb4bc7ecece50ca7fd473 Mon Sep 17 00:00:00 2001 From: OBS User autobuild Date: Fri, 12 Mar 2010 00:39:20 +0000 Subject: [PATCH 5/8] Accepting request 34653 from devel:tools checked in (request 34653) OBS-URL: https://build.opensuse.org/request/show/34653 OBS-URL: https://build.opensuse.org/package/show/devel:tools/systemtap?expand=0&rev=11 --- systemtap-1.0.tar.bz2 | 3 + systemtap-1.1.tar.bz2 | 3 - systemtap-CVE-2009-4273.diff | 925 ------------------ systemtap-CVE-2010-0411.diff | 187 ---- ...VE-limit-dwarf-expression-stack-size.patch | 135 +++ systemtap-CVE-limit-printf-arguments.patch | 75 ++ systemtap-CVE-unwind-table-size-checks.patch | 193 ++++ systemtap-docdir-fix.diff | 17 +- systemtap-docs.changes | 5 - systemtap-docs.spec | 19 +- systemtap-ioblock-suse-kernel-fix.diff | 12 +- systemtap-prevent-nested-arg.diff | 182 ---- systemtap-xmlto-fop.diff | 8 +- systemtap.changes | 13 - systemtap.spec | 94 +- 15 files changed, 467 insertions(+), 1404 deletions(-) create mode 100644 systemtap-1.0.tar.bz2 delete mode 100644 systemtap-1.1.tar.bz2 delete mode 100644 systemtap-CVE-2009-4273.diff delete mode 100644 systemtap-CVE-2010-0411.diff create mode 100644 systemtap-CVE-limit-dwarf-expression-stack-size.patch create mode 100644 systemtap-CVE-limit-printf-arguments.patch create mode 100644 systemtap-CVE-unwind-table-size-checks.patch delete mode 100644 systemtap-prevent-nested-arg.diff diff --git a/systemtap-1.0.tar.bz2 b/systemtap-1.0.tar.bz2 new file mode 100644 index 0000000..54bc50d --- /dev/null +++ b/systemtap-1.0.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a942ba85d6360023e6f8503a8dd4c8493d16b17cb474cc8f0ad5a50cec3607a +size 1205746 diff --git a/systemtap-1.1.tar.bz2 b/systemtap-1.1.tar.bz2 deleted file mode 100644 index 073b472..0000000 --- a/systemtap-1.1.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1d620a9861cd7c9609fb8012faf20eafb632f3f3a919bf0c08bec3a14924e3a2 -size 1293846 diff --git a/systemtap-CVE-2009-4273.diff b/systemtap-CVE-2009-4273.diff deleted file mode 100644 index 005f70a..0000000 --- a/systemtap-CVE-2009-4273.diff +++ /dev/null @@ -1,925 +0,0 @@ -Subject: VUL-0: systemtap-server code exec -References: bnc#574243 -Signed-Off-By: Tony Jones - -Fix remaining portions of this CVE (part2) still present post release-1.1 -This second part is also referred to as CVE-2010-0412 - -Covers cases such as stap-client -B CC=/bin/rm CFLAGS=/ ... where the -execution is done by make - - - -commit b75067caf1bb416af21473e40c917d953531e9f9 -Author: Dave Brolley -Date: Mon Jan 18 11:56:13 2010 -0500 - - Correct client-side quoting issues discovered by fche during the server-side reimplementation. - - Also add the test cases to the test suite. - -commit 241443ad36a5a2cacb9e8e6f12f808d304835f2a -Author: Dave Brolley -Date: Tue Feb 2 08:26:01 2010 -0500 - - PR 11105: Remaining client-side problems: - - stap-client: Correct handling of embedded newlines in arguments. - server_args.exp: Add additional cases discovered by fche and by fuzzing. - -commit 4240be911e37b817727ecb33f321f0ea389ede61 -Author: Dave Brolley -Date: Mon Feb 15 15:01:28 2010 -0500 - - Don't pass client-only options to the server. - - Also correct parsing of the --server option. - -commit d2334a2233f4efd055dab021c603f7c046730a66 -Author: Dave Brolley -Date: Tue Feb 2 14:08:31 2010 -0500 - - Compile server logging and robustness. - - Log certificate location and status when starting server. - Additional care in handling arguments in stap-serverd. - New test case discovered by fuzzing added and fixed. - -commit c0d1b5a004b9949bb455b7dbe17b335b7cab9ead -Author: Frank Ch. Eigler -Date: Fri Feb 12 10:25:43 2010 -0500 - - PR11105 part 2: tighten constraints on stap-server parameters passed to make - - * util.h, util.cxx (assert_match_regexp): New function. - * main.cxx (main): Constrain -R, -r, -a, -D, -S, -q, -B flags. - * stap-serverd (listen): Harden stap-server-connect with ulimit/loop. - * testsuite/systemtap.server/{client,server}_args.exp: Revised. - -commit cc9e5488d82b728e568bca1f8d6094856fc8e641 -Author: Frank Ch. Eigler -Date: Fri Feb 12 10:39:58 2010 -0500 - - PR11105 part 2a, fix buggy \\. in -r option regexp - ---- - main.cxx | 24 ++-- - stap-client | 151 +++++++++++++++++------------ - stap-gen-cert | 43 ++++---- - stap-serverd | 40 +++++-- - testsuite/systemtap.server/client_args.exp | 28 ++--- - testsuite/systemtap.server/hello.stp | 2 - testsuite/systemtap.server/server_args.exp | 49 +++++---- - util.cxx | 36 ++++++ - util.h | 2 - 9 files changed, 238 insertions(+), 137 deletions(-) - ---- a/main.cxx -+++ b/main.cxx -@@ -57,7 +57,7 @@ version () - << "SystemTap translator/driver " - << "(version " << VERSION << "/" << dwfl_version (NULL) - << " " << GIT_MESSAGE << ")" << endl -- << "Copyright (C) 2005-2009 Red Hat, Inc. and others" << endl -+ << "Copyright (C) 2005-2010 Red Hat, Inc. and others" << endl - << "This is free software; see the source for copying conditions." << endl; - } - -@@ -670,12 +670,12 @@ main (int argc, char * const argv []) - break; - - case 'o': -+ // NB: client_options not a problem, since pass 1-4 does not use output_file. - s.output_file = string (optarg); - break; - - case 'R': -- if (client_options) -- client_options_disallowed += client_options_disallowed.empty () ? "-R" : ", -R"; -+ if (client_options) { cerr << "ERROR: -R invalid with --client-options" << endl; usage(s,1); } - s.runtime_path = string (optarg); - break; - -@@ -684,6 +684,7 @@ main (int argc, char * const argv []) - client_options_disallowed += client_options_disallowed.empty () ? "-m" : ", -m"; - s.module_name = string (optarg); - save_module = true; -+ // XXX: convert to assert_regexp_match() - { - string::size_type len = s.module_name.length(); - -@@ -728,15 +729,14 @@ main (int argc, char * const argv []) - break; - - case 'r': -- if (client_options) -- client_options_disallowed += client_options_disallowed.empty () ? "-r" : ", -r"; -+ if (client_options) // NB: no paths! -+ assert_regexp_match("-r parameter from client", optarg, "^[a-z0-9_.-]+$"); - setup_kernel_release(s, optarg); - break; - - case 'a': -- if (client_options) -- client_options_disallowed += client_options_disallowed.empty () ? "-a" : ", -a"; -- s.architecture = string(optarg); -+ assert_regexp_match("-a parameter", optarg, "^[a-z0-9_-]+$"); -+ s.architecture = string(optarg); - break; - - case 'k': -@@ -783,16 +783,19 @@ main (int argc, char * const argv []) - break; - - case 'D': -+ assert_regexp_match ("-D parameter", optarg, "^[a-z_][a-z_0-9]*(=[a-z_0-9]+)?$"); - if (client_options) - client_options_disallowed += client_options_disallowed.empty () ? "-D" : ", -D"; - s.macros.push_back (string (optarg)); - break; - - case 'S': -+ assert_regexp_match ("-S parameter", optarg, "^[0-9]+(,[0-9]+)?$"); - s.size_option = string (optarg); - break; - - case 'q': -+ if (client_options) { cerr << "ERROR: -q invalid with --client-options" << endl; usage(s,1); } - s.tapset_compile_coverage = true; - break; - -@@ -823,9 +826,8 @@ main (int argc, char * const argv []) - break; - - case 'B': -- if (client_options) -- client_options_disallowed += client_options_disallowed.empty () ? "-B" : ", -B"; -- s.kbuildflags.push_back (string (optarg)); -+ if (client_options) { cerr << "ERROR: -B invalid with --client-options" << endl; usage(s,1); } -+ s.kbuildflags.push_back (string (optarg)); - break; - - case 0: ---- a/stap-client -+++ b/stap-client -@@ -2,7 +2,7 @@ - - # Compile server client for systemtap - # --# Copyright (C) 2008, 2009, 2010 Red Hat Inc. -+# Copyright (C) 2008-2010 Red Hat Inc. - # - # This file is part of systemtap, and is free software. You can - # redistribute it and/or modify it under the terms of the GNU General -@@ -84,34 +84,34 @@ function parse_options { - # Each command line argument will be written to its own file within the - # request package. - argc=1 -+ packed_options='-' - arg_subst= - - while test $# != 0 - do - advance=0 - dash_seen=0 -+ client_arg=0 - - # Start of a new token. - first_token="$1" - until test $advance != 0 - do - # Identify the next option -- first_char=`expr "$first_token" : '\(.\).*'` -+ first_char="${first_token:0:1}" - second_char= - if test $dash_seen = 0; then - if test "$first_char" = "-"; then - if test "$first_token" != "-"; then - # It's not a lone dash, so it's an option. - # Is it a long option (i.e. --option)? -- second_char=`expr "$first_token" : '.\(.\).*'` -+ second_char="${first_token:1:1}" - if test "X$second_char" = "X-"; then -- long_option=`expr "$first_token" : '--\(.*\)=.*'` -- test "X$long_option" != "X" || long_option=`expr "$first_token" : '--\(.*\)'` -- case $long_option in -- ssl) -+ case "$first_token" in -+ --ssl=*) - process_ssl "$first_token" - ;; -- server) -+ --server=*) - process_server "$first_token" - ;; - *) -@@ -123,9 +123,9 @@ function parse_options { - fi - # It's not a lone dash, or a long option, so it's a short option string. - # Remove the dash. -- first_token=`expr "$first_token" : '-\(.*\)'` -+ first_token="${first_token:1}" - dash_seen=1 -- first_char=`expr "$first_token" : '\(.\).*'` -+ first_char="${first_token:0:1}" - fi - fi - if test $dash_seen = 0; then -@@ -145,69 +145,69 @@ function parse_options { - # We are at the start of an option. Look at the first character. - case $first_char in - a) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_a "$stap_arg" - ;; - B) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - c) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_c "$stap_arg" - ;; - D) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - e) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_e "$stap_arg" - ;; - I) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_I "$stap_arg" - ;; - k) - keep_temps=1 - ;; - l) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - p_phase=2 - ;; - L) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - p_phase=2 - ;; - m) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_m "$stap_arg" - ;; - o) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_o "$stap_arg" - ;; - p) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_p "$stap_arg" - ;; - r) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_r "$stap_arg" - ;; - R) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - process_R "$stap_arg" - ;; - s) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - S) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - v) - v_level=$(($v_level + 1)) - ;; - x) -- get_arg $first_token "$2" -+ get_arg "$first_token" "$2" - ;; - *) - # An unknown or unimportant flag. -@@ -216,7 +216,7 @@ function parse_options { - - if test $advance = 0; then - # Just another flag character. Consume it. -- first_token=`expr "$first_token" : '.\(.*\)'` -+ first_token="${first_token:1}" - if test "X$first_token" = "X"; then - advance=$(($advance + 1)) - fi -@@ -224,9 +224,19 @@ function parse_options { - done - - # Consume the arguments we just processed. -- while test $advance != 0 -- do -- # Place the argument is a numbered file within our temp -+ while test $advance != 0; do -+ # Does the final argument file contain a client-side file -+ # name which must be changed to a server-side name? -+ local arg -+ if test "X$arg_subst" != "X" -a $advance = 1; then -+ arg="$arg_subst" -+ arg_subst= -+ else -+ arg="$1" -+ fi -+ -+ # If it's not client-only argument, -+ # place the argument in a numbered file within our temp - # directory. - # o We don't write a newline at the end, since newline could be - # part of the argument. -@@ -234,20 +244,16 @@ function parse_options { - # in order to avoid having 'echo' interpret the output as - # its own option. We then remove the X. - # There must be a better way. -- echo -n "X$1" > "$tmpdir_client/argv$argc" -- sed -i "s|^X||" "$tmpdir_client/argv$argc" -- -- # Does the final argument file contain client-side data -- # which must be changed to server-side data? -- if test "X$arg_subst" != "X" -a $advance = 1; then -- sed -i "s|$stap_arg|$arg_subst|" "$tmpdir_client/argv$argc" -- arg_subst= -+ if test $client_arg = 0; then -+ echo -n "X$arg" > "$tmpdir_client/argv$argc" -+ sed -i "s|^X||" "$tmpdir_client/argv$argc" -+ argc=$(($argc + 1)) - fi - - # Get the next argument. - shift -- argc=$(($argc + 1)) - advance=$(($advance - 1)) -+ packed_options='-' - done - done - -@@ -256,7 +262,8 @@ function parse_options { - if test "X$script_file" != "X"; then - local local_name - if test "$script_file" != "-"; then -- local_name=`generate_client_temp_name "$script_file"` -+ generate_client_temp_name "$script_file" -+ local_name="$client_temp_name" - else - local_name="-" - fi -@@ -277,8 +284,9 @@ function parse_options { - # Collect an argument to the given option - function get_arg { - # Remove first character. -- local opt=`expr "$1" : '\(.\).*'` -- local first=`expr "$1" : '.\(.*\)'` -+ local opt="${1:0:1}" -+ local first="${1:1}" -+ packed_options="${packed_options}$opt" - - # Advance to the next token, if the first one is exhausted. - if test "X$first" = "X"; then -@@ -294,7 +302,8 @@ function get_arg { - # - # Process the --ssl option. - function process_ssl { -- local db=`expr "$1" : '--ssl=\(.*\)'` -+ client_arg=1 -+ local db="${1:6}" - - test "X$db" != "X" || \ - fatal "Missing argument to --ssl" -@@ -308,7 +317,8 @@ function process_ssl { - # - # Process the --server option. - function process_server { -- local spec=`expr "$1" : '--server=\(.*\)'` -+ client_arg=1 -+ local spec="${1:9}" - - test "X$spec" != "X" || \ - fatal "Missing argument to --server" -@@ -335,12 +345,19 @@ function process_e { - fi - } - --# function: process_I ARGUMENT -+# function: process_I ARGUMENT ORIGINAL_ARGUMENT - # - # Process the -I flag. - function process_I { - test "X$1" = "X" && return -- arg_subst=tapsets/`include_file_or_directory tapsets "$1"` -+ test "${1:0:1}" = " -+" && return -+ include_file_or_directory tapsets "$1" -+ if test $advance = 1; then -+ arg_subst="${packed_options}tapsets/$included_name" -+ else -+ arg_subst="tapsets/$included_name" -+ fi - } - - # function: process_m ARGUMENT -@@ -369,7 +386,7 @@ function process_p { - # - # Process the -r flag. - function process_r { -- local first_char=`expr "$1" : '\(.\).*'` -+ local first_char="${1:0:1}" - - if test "$first_char" = "/"; then # fully specified path - kernel_build_tree="$1" -@@ -402,23 +419,34 @@ function process_a { - fi - } - --# function: process_R ARGUMENT -+# function: process_R ARGUMENT ORIGINAL_ARGUMENT - # - # Process the -R flag. - function process_R { - test "X$1" = "X" && return -- arg_subst=runtime/`include_file_or_directory runtime "$1"` -+ test "${1:0:1}" = " -+" && return -+ include_file_or_directory runtime "$1" -+ if test $advance = 1; then -+ arg_subst="${packed_options}runtime/$included_name" -+ else -+ arg_subst="runtime/$included_name" -+ fi - } - - # function: include_file_or_directory PREFIX NAME - # - # Include the given file or directory in the client's temporary --# tree to be sent to the server. -+# tree to be sent to the server and save it's name in the variable -+# included_name. We use a global variable instread of echoing the -+# result since the use of `include_file_or_directory` loses a trailing -+# newline. - function include_file_or_directory { - # Add a symbolic link of the named file or directory to our temporary - # directory, but only if the file or directory exists. -- local local_name=`generate_client_temp_name "$2"` -- echo "$local_name" -+ generate_client_temp_name "$2" -+ local local_name="$client_temp_name" -+ included_name="$local_name" - test -e "/$local_name" || return - - local local_dirname=`dirname "$local_name"` -@@ -431,15 +459,20 @@ function include_file_or_directory { - # function: generate_client_temp_name NAME - # - # Generate the name to be used for the given file/directory relative to the --# client's temporary directory. -+# client's temporary directory and stores it in the variable -+# client_temp_name. We use a global variable instread of echoing the -+# result since the use of `generate_client_temp_name` loses a trailing -+# newline. - function generate_client_temp_name { - # Transform the name into a fully qualified path name -- local full_name=`echo "X$1" | sed "s,^X\\\([^/]\\\),$wd/\\\\1," | sed 's,^X,,'` -+ local full_name="$1" -+ test "${full_name:0:1}" != "/" && full_name="$wd/$full_name" - - # The same name without the initial / or trailing / -- local local_name=`echo "$full_name" | sed 's,^/\(.*\),\1,'` -- local_name=`echo "$local_name" | sed 's,\(.*\)/$,\1,'` -- echo "$local_name" -+ local local_name="${full_name:1}" -+ test "${local_name: -1:1}" = "/" && local_name="${local_name:0:$((${#local_name}-1))}" -+ -+ client_temp_name="$local_name" - } - - # function: create_request -@@ -456,7 +489,7 @@ function create_request { - fatal "Cannot create temporary directory " $tmpdir_client/script - cat > "$tmpdir_client/script/$script_file" - else -- include_file_or_directory script "$script_file" > /dev/null -+ include_file_or_directory script "$script_file" - fi - fi - -@@ -505,7 +538,7 @@ function unpack_response { - # 2) a file called stderr - # 3) a file called rc - # 4) optionally a directory named to match stap?????? -- num_files=`ls $tmpdir_server | wc -l` -+ local num_files=`ls $tmpdir_server | wc -l` - test $num_files = 4 -o $num_files = 3 || \ - fatal "Wrong number of files in server's temp directory" - test -f $tmpdir_server/stdout || \ ---- a/stap-gen-cert -+++ b/stap-gen-cert -@@ -3,7 +3,7 @@ - # Generate a certificate for the systemtap server and add it to the - # database of trusted servers for the client. - # --# Copyright (C) 2008, 2009 Red Hat Inc. -+# Copyright (C) 2008-2010 Red Hat Inc. - # - # This file is part of systemtap, and is free software. You can - # redistribute it and/or modify it under the terms of the GNU General -@@ -14,61 +14,68 @@ - . ${PKGLIBEXECDIR}stap-env - - # Obtain the certificate database directory name. --serverdb=$1 -+serverdb="$1" - if test "X$serverdb" = "X"; then -- serverdb=$stap_ssl_db/server -+ serverdb="$stap_ssl_db/server" - fi --rm -fr $serverdb -+rm -fr "$serverdb" - - # Create the server's certificate database directory. --if ! mkdir -p -m 755 $serverdb; then -+if ! mkdir -p -m 755 "$serverdb"; then - echo "Unable to create the server certificate database directory: $serverdb" >&2 - exit 1 - fi - - # Create the certificate database password file. Care must be taken - # that this file is only readable by the owner. --if ! (touch $serverdb/pw && chmod 600 $serverdb/pw); then -+if ! (touch "$serverdb/pw" && chmod 600 "$serverdb/pw"); then - echo "Unable to create the server certificate database password file: $serverdb/pw" >&2 - exit 1 - fi - - # Generate a random password. --mkpasswd -l 20 > $serverdb/pw 2>/dev/null || \ --apg -a 1 -n 1 -m 20 -x 20 > $serverdb/pw 2>/dev/null || \ --(read -n20 password $serverdb/pw) -+mkpasswd -l 20 > "$serverdb/pw" 2>/dev/null || \ -+apg -a 1 -n 1 -m 20 -x 20 > "$serverdb/pw" 2>/dev/null || \ -+(read -n20 password "$serverdb/pw") - - # Generate the server certificate database --if ! certutil -N -d $serverdb -f $serverdb/pw > /dev/null; then -+if ! certutil -N -d "$serverdb" -f "$serverdb/pw" > /dev/null; then - echo "Unable to initialize the server certificate database directory: $serverdb" >&2 - exit 1 - fi - - # We need some random noise for generating keys --dd bs=123 count=1 < /dev/urandom > $serverdb/noise 2> /dev/null -+dd bs=123 count=1 < /dev/urandom > "$serverdb/noise" 2> /dev/null - - # Generate a request for the server's certificate. --certutil -R -d $serverdb -f $serverdb/pw -s "CN=Systemtap Compile Server, OU=Systemtap, O=Red Hat, C=US" -o $serverdb/stap.req -z $serverdb/noise 2> /dev/null --rm -fr $serverdb/noise -+certutil -R -d "$serverdb" -f "$serverdb/pw" -s "CN=Systemtap Compile Server, OU=Systemtap, O=Red Hat, C=US" \ -+ -o "$serverdb/stap.req" -z "$serverdb/noise" 2> /dev/null -+rm -fr "$serverdb/noise" - - # Create the certificate file first so that it always has the proper access permissions. --if ! (touch $serverdb/$stap_certfile && chmod 644 $serverdb/$stap_certfile); then -+if ! (touch "$serverdb/$stap_certfile" && chmod 644 "$serverdb/$stap_certfile"); then - echo "Unable to create the server certificate file: $serverdb/$stap_certfile" >&2 - exit 1 - fi - --# Now generate the actual certificate. --certutil -C -i $serverdb/stap.req -o $serverdb/$stap_certfile -x -d $serverdb -f $serverdb/pw -5 -8 "$HOSTNAME,localhost" >/dev/null <<-EOF -+# Now generate the actual certificate. Make is valid for 1 year. -+certutil -C -i "$serverdb/stap.req" -o "$serverdb/$stap_certfile" -x -d "$serverdb" \ -+ -f "$serverdb/pw" -v 12 -5 -8 "$HOSTNAME,localhost" >/dev/null <<-EOF - 1 - 3 - 7 - 8 - y - EOF --rm -fr $serverdb/stap.req -+rm -fr "$serverdb/stap.req" - - # Add the certificate to the server's certificate/key database as a trusted peer, ssl server and object signer --certutil -A -n stap-server -t "PCu,,PCu" -i $serverdb/$stap_certfile -d $serverdb -f $serverdb/pw -+certutil -A -n stap-server -t "PCu,,PCu" -i "$serverdb/$stap_certfile" -d "$serverdb" -f "$serverdb/pw" - -+# Print some information about the certificate. - echo "Certificate $serverdb/$stap_certfile created and added to database $serverdb" -+certutil -L -d "$serverdb" -n stap-server | \ -+ awk '/Validity|Not After|Not Before/ { print $0 }' | \ -+ sed 's/^ */ /' -+ - exit 0 ---- a/stap-serverd -+++ b/stap-serverd -@@ -70,12 +70,18 @@ function initialization { - -x `which ${stap_exec_prefix}stap-client 2>/dev/null`; then - ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 - fi -- elif ! test -f $stap_ssl_db/client/cert8.db; then -- # If the client's database does not exist, then initialize it with our certificate. -- # Do this only if the client has been installed. -- if test -f `which ${stap_exec_prefix}stap-client` -a \ -- -x `which ${stap_exec_prefix}stap-client`; then -- ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 -+ else -+ echo "Certificate found in database $ssl_db" >> $logfile -+ certutil -L -d "$ssl_db" -n stap-server | \ -+ awk '/Validity|Not After|Not Before/ { print $0 }' | \ -+ sed 's/^ */ /' >> $logfile -+ if ! test -f $stap_ssl_db/client/cert8.db; then -+ # If the client's database does not exist, then initialize it with our certificate. -+ # Do this only if the client has been installed. -+ if test -f `which ${stap_exec_prefix}stap-client 2>/dev/null` -a \ -+ -x `which ${stap_exec_prefix}stap-client 2>/dev/null`; then -+ ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 -+ fi - fi - fi - fi -@@ -343,11 +349,19 @@ function advertise_presence { - function listen { - # The stap-server-connect program will listen forever - # accepting requests. -- ${stap_pkglibexecdir}stap-server-connect \ -- -p $port -n $nss_cert -d $ssl_db -w $nss_pw \ -- -s "$stap_options" \ -- >> $logfile 2>&1 & -- wait '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 -+ # CVE-2009-4273 ... or at least, until resource limits fire -+ while true; do # NB: loop to avoid DoS by deliberate rlimit-induced halt -+ # NB: impose resource limits in case of mischevious data inducing -+ # too much / long computation -+ (ulimit -f 50000 -s 1000 -t 60 -u 20 -v 500000; -+ exec ${stap_pkglibexecdir}stap-server-connect \ -+ -p $port -n $nss_cert -d $ssl_db -w $nss_pw \ -+ -s "$stap_options") & -+ stap_server_connect_pid=$! -+ wait -+ # NB: avoid superfast spinning in case of a ulimit or other failure -+ sleep 1 -+ done >> $logfile 2>&1 - } - - # function: warning [ MESSAGE ] -@@ -379,8 +393,8 @@ function terminate { - wait '%avahi-publish-service' >> $logfile 2>&1 - - # Kill any running 'stap-server-connect' job. -- kill -s SIGTERM '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 -- wait '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 -+ kill -s SIGTERM $stap_server_connect_pid >> $logfile 2>&1 -+ wait $stap_server_connect_pid >> $logfile 2>&1 - - exit - } ---- a/testsuite/systemtap.server/client_args.exp -+++ b/testsuite/systemtap.server/client_args.exp -@@ -5,33 +5,34 @@ set test "Invalid Server Client Argument - set test_file $srcdir/systemtap.server/test.stp - - # Test invalid combinations. --set error_regexp ".*You can't specify .* when --unprivileged is specified.*" -+set error_regexp ".*(ERROR)|(You can't specify .* when --unprivileged is specified).*" - - set invalid_options [list \ -- "--unprivileged --client-options -a i386" \ - "--unprivileged --client-options -B X=Y" \ - "--unprivileged --client-options -D X=Y" \ - "--unprivileged --client-options -I /tmp" \ - "--unprivileged --client-options -m test" \ - "--unprivileged --client-options -R /tmp" \ -- "--unprivileged --client-options -r [exec uname -r]" \ -- "--unprivileged --client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ -- "--client-options --unprivileged -a i386" \ -+ "--unprivileged --client-options -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ - "--client-options --unprivileged -B X=Y" \ - "--client-options --unprivileged -D X=Y" \ - "--client-options --unprivileged -I /tmp" \ - "--client-options --unprivileged -m test" \ - "--client-options --unprivileged -R /tmp" \ -- "--client-options --unprivileged -r [exec uname -r]" \ -- "--client-options --unprivileged -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ -- "--client-options -a i386 --unprivileged" \ -+ "--client-options --unprivileged -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ - "--client-options -B X=Y --unprivileged" \ - "--client-options -D X=Y --unprivileged" \ - "--client-options -I /tmp --unprivileged" \ - "--client-options -m test --unprivileged" \ - "--client-options -R /tmp --unprivileged" \ -- "--client-options -r [exec uname -r] --unprivileged" \ -- "--client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r] --unprivileged" \ -+ "--client-options -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r] --unprivileged" \ -+ "--client-options -R /path" \ -+ "-D \"foo;bar\"" \ -+ "-D 2=4" \ -+ "-D \"foo;bar\"" \ -+ "--client-options -r /path" \ -+ "-S /path" \ -+ "--client-options -q" \ - ] - - foreach options $invalid_options { -@@ -66,9 +67,8 @@ set valid_options [list \ - "-D X=Y" \ - "-I /tmp" \ - "-m test" \ -- "-R /tmp" \ - "-r [exec uname -r]" \ -- "-a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ -+ "-a i386 -B X=Y -D X=Y -I /tmp -m test -r [exec uname -r]" \ - "--unprivileged" \ - "--unprivileged -a i386" \ - "--unprivileged -B X=Y" \ -@@ -80,13 +80,11 @@ set valid_options [list \ - "--unprivileged -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ - "--client-options" \ - "--client-options -a i386" \ -- "--client-options -B X=Y" \ - "--client-options -D X=Y" \ - "--client-options -I /tmp" \ - "--client-options -m test" \ -- "--client-options -R /tmp" \ - "--client-options -r [exec uname -r]" \ -- "--client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ -+ "--client-options -a i386 -D X=Y -I /tmp -m test -r [exec uname -r]" \ - "--unprivileged --client-options" \ - "--client-options --unprivileged" \ - "--unprivileged -a i386 --client-options" \ ---- a/testsuite/systemtap.server/hello.stp -+++ b/testsuite/systemtap.server/hello.stp -@@ -1,4 +1,4 @@ --#! stap -+#! stap -p5 - - probe begin - { ---- a/testsuite/systemtap.server/server_args.exp -+++ b/testsuite/systemtap.server/server_args.exp -@@ -40,11 +40,13 @@ proc stap_direct_and_with_client {stap s - # Some messages contain the names of files or directories - # and will be prefixed for the client. - if {[regexp "^ (.*)" $expected_line match data]} { -- if {[regexp "^ tapsets/.*/$data" $line]} { -+ # Special characters in the regexp need to be quoted. -+ regsub -all "\[\"\\\\;\*\]" $data {\\\0} data -+ if {[regexp "^ tapsets.*/$data" $line]} { - incr n - continue - } -- if {[regexp "^ runtime/.*/$data" $line]} { -+ if {[regexp "^ runtime.*/$data" $line]} { - incr n - continue - } -@@ -57,7 +59,9 @@ proc stap_direct_and_with_client {stap s - } - } else { - if {[regexp "^Input file '(.*)' is empty or missing." $expected_line match data]} { -- if {[regexp "^Input file 'script/.*/$data' is empty or missing." $line]} { -+ # Special characters in the regexp need to be quoted. -+ regsub -all "\[\"\\\\;\*\]" $data {\\\0} data -+ if {[regexp "^Input file 'script.*/$data' is empty or missing." $line]} { - incr n - continue - } -@@ -110,21 +114,27 @@ if {[installtest_p]} then { - # for debugging a currently failing case and helps to ensure that previously - # fixed cases do not regress. - set previously_fixed [list \ -+ "-p1 -I=\\w94\nbh -e -Dhfuo0iu7 -c" \ -+ "-p1 -I8o\\2ie -e'1\\ -D\n\" -c" \ -+ "-p1 -Ira\\3;c g -e0fle'qq -Dr/316k\\o8 -cjyoc\n3" \ -+ "-p1 -I6p3 -elc -Dqgsgv' -c" \ -+ "-p1 -I\"vyv;z -ej\"/3 -D/ 01qck\n -c3u55zut" \ -+ "-p1 -I1 -eo9e\nx047q -D9xyefk0a -cvl98/x1'i" \ - "-p1 -c; test.stp" \ -- "-p1 -I4hgy96 -R -e5oo39p -Bile\\vp -Ddx8v -c4;" \ -- "-p1 -I -Repwd9 -esq3wors -Btmk;\\t -Dz -c*eibz8h2e" \ -- "-p1 -I -Ry a -em339db5 -B;ae41428d -Du2;c0ps -ch9o\\" \ -- "-p1 -Ipfjps4 -Rx479 -ebug4dc -Bih;fe2 -Du8vd fvkl -c" \ -- "-p1 -I0\"nspzjyf -R -e5r3up8h -Bgqnyjq6w -Dmi;ojp9m -cx;a2fat" \ -- "-p1 -Iu -R9 -ek7;r -Big -Dcu\"; -c\"hc" \ -- "-p1 -Icd4fidq -Rkj m40mv -edn -B7ria -D;8ha\\cjr -c1*vnq" \ -- "-p1 -I;3 -R3lq;vp -er8e -Bgdqjqdy -D -cb6k29z" \ -- "-p1 -Ircj -R -e -B -D -c\\vmww" \ -- "-p1 -Illc5 -Rug*\\o -e65wof9 -B qr*=x7x5 -D -cgx;" \ -- "-p1 -Iyaj420=3 -R -e\" -Bx68j -D -cd'5mi" \ -- "-p1 -Ir -Rwd8;;sjl -e -Bxh; -D29\\ -cj2szt;4" \ -- "-p1 -Ibno3=b4sk -R*5 -e' -Byl63flos -Dg2-j;e -c2ijx'" \ -- "-p1 -I285v7pl -R9a -eo5\\0 -Bfs* -D86s -c-c*v" \ -+ "-p1 -I4hgy96 -e5oo39p -Ddx8v -c4;" \ -+ "-p1 -I -esq3wors -Dz -c*eibz8h2e" \ -+ "-p1 -I a -em339db5 -Du2;c0ps -ch9o\\" \ -+ "-p1 -Ipfjps4 -ebug4dc -Du8vd fvkl -c" \ -+ "-p1 -I0\"nspzjyf -e5r3up8h -Dmi;ojp9m -cx;a2fat" \ -+ "-p1 -Iu -ek7;r -Dcu\"; -c\"hc" \ -+ "-p1 -Icd4fidq m40mv -edn -D;8ha\\cjr -c1*vnq" \ -+ "-p1 -I;3 -er8e -D -cb6k29z" \ -+ "-p1 -Ircj -e -D -c\\vmww" \ -+ "-p1 -Illc5 -e65wof9 qr*=x7x5 -D -cgx;" \ -+ "-p1 -Iyaj420=3 -e\" -D -cd'5mi" \ -+ "-p1 -Ir -e -D29\\ -cj2szt;4" \ -+ "-p1 -Ibno3=b4sk -e' -Dg2-j;e -c2ijx'" \ -+ "-p1 -I285v7pl -eo5\\0 -D86s -c-c*v" \ - ] - - set i 0 -@@ -140,7 +150,10 @@ foreach options $previously_fixed { - # Generate semi-random arguments containing with potential problem characters. - # Check that running systemtap with the client/server generates output - # comparable to running stap directly. --set dangerous_options [list "-I" "-R" "-e" "-B" "-D" "-c"] -+set dangerous_options [list "-I" "-e" "-D" "-c" "-S"] -+# NB: Other options could be candidates here, like -r and -B, but -+# there stap-server imposes more restrictions than local stap, so -+# this simple error-matching test cannot use them. - set argchars "0123456789/;*'=-\\\"\n abcdefghijklmnopqrstuvwxyz" - - for {set i 0} {$i < $iterations} {incr i} { ---- a/util.cxx -+++ b/util.cxx -@@ -1,5 +1,5 @@ - // Copyright (C) Andrew Tridgell 2002 (original file) --// Copyright (C) 2006, 2009 Red Hat Inc. (systemtap changes) -+// Copyright (C) 2006-2010 Red Hat Inc. (systemtap changes) - // - // This program is free software; you can redistribute it and/or - // modify it under the terms of the GNU General Public License as -@@ -19,6 +19,8 @@ - #include "sys/sdt.h" - #include - #include -+#include -+#include - - extern "C" { - #include -@@ -31,6 +33,7 @@ extern "C" { - #include - #include - #include -+#include - } - - using namespace std; -@@ -413,4 +416,35 @@ kill_stap_spawn(int sig) - return spawned_pid ? kill(spawned_pid, sig) : 0; - } - -+ -+void assert_regexp_match (const string& name, const string& value, const string& re) -+{ -+ typedef map cache; -+ static cache compiled; -+ cache::iterator it = compiled.find (re); -+ regex_t* r = 0; -+ if (it == compiled.end()) -+ { -+ r = new regex_t; -+ int rc = regcomp (r, re.c_str(), REG_ICASE|REG_NOSUB|REG_EXTENDED); -+ if (rc) { -+ cerr << "regcomp " << re << " (" << name << ") error rc=" << rc << endl; -+ exit(1); -+ } -+ compiled[re] = r; -+ } -+ else -+ r = it->second; -+ -+ // run regexec -+ int rc = regexec (r, value.c_str(), 0, 0, 0); -+ if (rc) -+ { -+ cerr << "ERROR: Safety pattern mismatch for " << name -+ << " ('" << value << "' vs. '" << re << "') rc=" << rc << endl; -+ exit(1); -+ } -+} -+ -+ - /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ ---- a/util.h -+++ b/util.h -@@ -21,7 +21,7 @@ const std::string cmdstr_quoted(const st - std::string git_revision(const std::string& path); - int stap_system(int verbose, const std::string& command); - int kill_stap_spawn(int sig); -- -+void assert_regexp_match (const std::string& name, const std::string& value, const std::string& re); - - // stringification generics - diff --git a/systemtap-CVE-2010-0411.diff b/systemtap-CVE-2010-0411.diff deleted file mode 100644 index 59cf89a..0000000 --- a/systemtap-CVE-2010-0411.diff +++ /dev/null @@ -1,187 +0,0 @@ -Subject: VUL-1: systemtap: DoS issue in __get_argv() function -References: bnc#577382 -Signed-Off-By: Tony Jones - -commit a2d399c87a642190f08ede63dc6fc434a5a8363a -Author: Josh Stone -Date: Thu Feb 4 17:47:31 2010 -0800 - - PR11234: Rewrite __get_argv without embedded-C - - We now implement __get_argv's string building in pure stap script. - Also, every argument is now quoted, which is different than before, but - it's much more robust about handling special characters. - -diff --git a/tapset/aux_syscalls.stp b/tapset/aux_syscalls.stp -index bab0f64..e762b37 100644 ---- a/tapset/aux_syscalls.stp -+++ b/tapset/aux_syscalls.stp -@@ -399,124 +399,53 @@ function __sem_flags:string(semflg:long) - - - /* This function copies an argv from userspace. */ --function __get_argv:string(a:long, first:long) --%{ /* pure */ -- char __user *__user *argv = (char __user *__user *)(long)THIS->a; -- char __user *vstr; -- int space, rc, len = MAXSTRINGLEN; -- char *str = THIS->__retvalue; -- char buf[80]; -- char *ptr = buf; -- -- -- if (THIS->first && argv) -- argv++; -- -- while (argv != NULL) { -- if (__stp_get_user (vstr, argv)) -- break; -- -- if (vstr == NULL) -- break; -- -- rc = _stp_strncpy_from_user(buf, vstr, 79); -- if (rc <= 0) -- break; -- -- /* check for whitespace in string */ -- buf[rc] = 0; -- ptr = buf; -- space = 0; -- while (*ptr && rc--) { -- if (isspace(*ptr++)) { -- space = 1; -- break; -- } -- } -- -- if (len != MAXSTRINGLEN && len) { -- *str++=' '; -- len--; -- } -- -- if (space && len) { -- *str++='\"'; -- len--; -- } -- -- rc = strlcpy (str, buf, len); -- str += rc; -- len -= rc; -- -- if (space && len) { -- *str++='\"'; -- len--; -- } -- -- argv++; -+function __get_argv:string(argv:long, first:long) -+{ -+%( CONFIG_64BIT == "y" %? -+ if (first && argv) -+ argv += 8 -+ while (argv) { -+ vstr = user_long(argv) -+ if (!vstr) -+ break -+ if (len) -+ str .= " " -+ str .= user_string_quoted(vstr) -+ -+ newlen = strlen(str) -+ if (newlen == len) -+ break -+ len = newlen -+ argv += 8 - } -- *str = 0; --%} --/* This function copies an argv from userspace. */ --function __get_compat_argv:string(a:long, first:long) --%{ /* pure */ --#ifdef CONFIG_COMPAT -- compat_uptr_t __user *__user *argv = (compat_uptr_t __user *__user *)(long)THIS->a; -- compat_uptr_t __user *vstr; -- int space, rc, len = MAXSTRINGLEN; -- char *str = THIS->__retvalue; -- char buf[80]; -- char *ptr = buf; -- -- if (THIS->first && argv) -- argv++; -- -- while (argv != NULL) { -- if (__stp_get_user (vstr, argv)) -- break; -- -- if (vstr == NULL) -- break; -- -- rc = _stp_strncpy_from_user(buf, (char *)vstr, 79); -- if (rc <= 0) -- break; -- -- /* check for whitespace in string */ -- buf[rc] = 0; -- ptr = buf; -- space = 0; -- while (*ptr && rc--) { -- if (isspace(*ptr++)) { -- space = 1; -- break; -- } -- } -- -- if (len != MAXSTRINGLEN && len) { -- *str++=' '; -- len--; -- } -- -- if (space && len) { -- *str++='\"'; -- len--; -- } -- -- rc = strlcpy (str, buf, len); -- str += rc; -- len -= rc; -- -- if (space && len) { -- *str++='\"'; -- len--; -- } - -- argv++; -+ return str -+%: -+ return __get_compat_argv(argv, first) -+%) -+} -+/* This function copies an argv from userspace. */ -+function __get_compat_argv:string(argv:long, first:long) -+{ -+ if (first && argv) -+ argv += 4 -+ while (argv) { -+ vstr = user_int(argv) & 0xffffffff -+ if (!vstr) -+ break -+ if (len) -+ str .= " " -+ str .= user_string_quoted(vstr) -+ -+ newlen = strlen(str) -+ if (newlen == len) -+ break -+ len = newlen -+ argv += 4 - } -- *str = 0; --#endif --%} -+ -+ return str -+} - - /* - * Return the symbolic string representation diff --git a/systemtap-CVE-limit-dwarf-expression-stack-size.patch b/systemtap-CVE-limit-dwarf-expression-stack-size.patch new file mode 100644 index 0000000..4394e4f --- /dev/null +++ b/systemtap-CVE-limit-dwarf-expression-stack-size.patch @@ -0,0 +1,135 @@ +From: Jan Lieskovsky +Subject: Three SystemTap-1.0 denial of service issues +References: CVE-2009-2911, BNC#548361 +Upstream: yes + + Three denial of service flaws were found in the SystemTap +instrumentation system of version 1.0, when the --unprivileged mode was +activated: + +b, Kernel stack frame overflow allows local attackers to cause denial +of service via specially-crafted user-provided DWARF information. + +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/systemtap-CVE-limit-printf-arguments.patch b/systemtap-CVE-limit-printf-arguments.patch new file mode 100644 index 0000000..32041a0 --- /dev/null +++ b/systemtap-CVE-limit-printf-arguments.patch @@ -0,0 +1,75 @@ +From: Jan Lieskovsky +Subject: Three SystemTap-1.0 denial of service issues +References: CVE-2009-2911, BNC#548361 +Upstream: yes + + Three denial of service flaws were found in the SystemTap +instrumentation system of version 1.0, when the --unprivileged mode was +activated: + +a, Kernel stack overflow allows local attackers to cause denial of service or +execute arbitrary code via long number of parameters, provided to the print* +call. + +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 tmp; + + diff --git a/systemtap-CVE-unwind-table-size-checks.patch b/systemtap-CVE-unwind-table-size-checks.patch new file mode 100644 index 0000000..408239b --- /dev/null +++ b/systemtap-CVE-unwind-table-size-checks.patch @@ -0,0 +1,193 @@ +From: Jan Lieskovsky +Subject: Three SystemTap-1.0 denial of service issues +References: CVE-2009-2911, BNC#548361 +Upstream: yes + + Three denial of service flaws were found in the SystemTap +instrumentation system of version 1.0, when the --unprivileged mode was +activated: + +c, Absent check(s) for the upper bound of the size of the unwind table + and for the upper bound of the size of each of the CIE/CFI records, could + allow an attacker to cause a denial of service (infinite loop). + +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 != ¬_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 == ¬_fde || (ptrType = fde_pointer_type(cie)) < 0) ++ if (cie == NULL || cie == ¬_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 + } + ++// 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/systemtap-docdir-fix.diff b/systemtap-docdir-fix.diff index ecdced0..9cb4ad9 100644 --- a/systemtap-docdir-fix.diff +++ b/systemtap-docdir-fix.diff @@ -1,10 +1,3 @@ -From: Tony Jones -Subject: change doc install path -References: none -Upstream: never - -SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. - --- Makefile.am | 2 +- doc/Makefile.am | 2 +- @@ -14,15 +7,15 @@ SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. --- a/Makefile.am +++ b/Makefile.am -@@ -257,7 +257,7 @@ install-data-local: +@@ -218,7 +218,7 @@ | while read f; do if test -x $$f; then \ i_cmd="$(INSTALL_PROGRAM)"; else \ i_cmd="$(INSTALL_DATA)"; fi; \ - $$i_cmd -D $$f $(DESTDIR)$(docdir)/examples/$$f; done) + $$i_cmd -D $$f $(DESTDIR)$(datadir)/doc/packages/systemtap/examples/$$f; done) test -e $(DESTDIR)$(sysconfdir)/systemtap || mkdir -p $(DESTDIR)$(sysconfdir)/systemtap - if BUILD_SERVER - test -e $(DESTDIR)$(localstatedir)/run/stap-server || mkdir -p $(DESTDIR)$(localstatedir)/run/stap-server + + TEST_COV_DIR = coverage --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -2,7 +2,7 @@ @@ -31,7 +24,7 @@ SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. PDF_FILES = tutorial.pdf langref.pdf -DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap +DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/packages/systemtap - SUBDIRS = SystemTap_Tapset_Reference beginners + SUBDIRS = SystemTap_Tapset_Reference if BUILD_DOCS --- a/doc/SystemTap_Tapset_Reference/Makefile.am @@ -50,7 +43,7 @@ SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. ### --- a/stapex.3stap.in +++ b/stapex.3stap.in -@@ -114,12 +114,12 @@ To list the probeable functions and loca +@@ -114,12 +114,12 @@ .SH MORE EXAMPLES Larger examples, demos and samples can be found in diff --git a/systemtap-docs.changes b/systemtap-docs.changes index 1a076e3..8573048 100644 --- a/systemtap-docs.changes +++ b/systemtap-docs.changes @@ -1,8 +1,3 @@ -------------------------------------------------------------------- -Thu Mar 11 22:49:52 UTC 2010 - tonyj@novell.com - -- Update to version 1.1. See systemtap.changes for full changelog. - ------------------------------------------------------------------- Wed Dec 2 23:52:10 UTC 2009 - tonyj@novell.com diff --git a/systemtap-docs.spec b/systemtap-docs.spec index 04b348f..35adc8f 100644 --- a/systemtap-docs.spec +++ b/systemtap-docs.spec @@ -1,5 +1,5 @@ # -# spec file for package systemtap-docs (Version 1.1) +# spec file for package systemtap-docs (Version 1.0) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -22,11 +22,13 @@ Name: systemtap-docs BuildRequires: gcc-c++ libebl-devel pkg-config # for documents BuildRequires: xmlto +%if %suse_version > 1030 BuildRequires: fop BuildRequires: latex2html +%endif %define use_snapshot 0 License: GPLv2+ -Version: 1.1 +Version: 1.0 Release: 1 Summary: Documents and examples for systemtap Group: Development/Tools/Debuggers @@ -37,7 +39,7 @@ Url: http://sourceware.org/systemtap/ %define package_version %{version} %endif Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 -Patch1: systemtap-docdir-fix.diff +Patch: systemtap-docdir-fix.diff Patch2: systemtap-xmlto-fop.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch @@ -61,8 +63,10 @@ Authors: %else %setup -n systemtap-%{package_version} -q %endif -%patch1 -p1 +%patch -p1 +%if %suse_version > 1030 %patch2 -p1 +%endif %build autoreconf -fi @@ -70,9 +74,12 @@ autoreconf -fi make %{?jobs:-j %jobs} %install +%if %suse_version < 1030 +# workaround for old autoconf +export MKDIR_P="mkdir -p" +%endif %makeinstall doc -# COPYING packaged by main spec -cp README AUTHORS NEWS $RPM_BUILD_ROOT%{_docdir}/systemtap/ +cp README AUTHORS NEWS COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ # remove binaries and runtime stuff rm -rf $RPM_BUILD_ROOT%{_bindir} rm -rf $RPM_BUILD_ROOT%{_libexecdir} diff --git a/systemtap-ioblock-suse-kernel-fix.diff b/systemtap-ioblock-suse-kernel-fix.diff index 3f12a69..e274cd6 100644 --- a/systemtap-ioblock-suse-kernel-fix.diff +++ b/systemtap-ioblock-suse-kernel-fix.diff @@ -1,10 +1,6 @@ ---- - tapset/ioblock.stp | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - ---- a/tapset/ioblock.stp -+++ b/tapset/ioblock.stp -@@ -118,7 +118,7 @@ probe ioblock.request = kernel.function +--- a/tapset/ioblock.stp-dist 2008-12-05 08:14:19.000000000 +0100 ++++ b/tapset/ioblock.stp 2008-12-05 08:14:27.000000000 +0100 +@@ -122,7 +122,7 @@ vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments @@ -13,7 +9,7 @@ hw_segments = $bio->bi_hw_segments %) size = $bio->bi_size -@@ -169,7 +169,7 @@ probe ioblock.end = kernel.function("bio +@@ -178,7 +178,7 @@ vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments diff --git a/systemtap-prevent-nested-arg.diff b/systemtap-prevent-nested-arg.diff deleted file mode 100644 index 8633db2..0000000 --- a/systemtap-prevent-nested-arg.diff +++ /dev/null @@ -1,182 +0,0 @@ -From: Josh Stone -Date: Tue Jan 19 15:36:35 2010 -0800 -Git-Repo: git://sources.redhat.com/git/systemtap.git -Git-Commit: 9300f661214a4f4dfac75878485867b30c7db389 -Signed-Off-By: Tony Jones - - tonyj: this fixes parse errors such as: - parse error: expected 'probe', 'global', 'function', or '%{' - saw: identifier '?robe' at - - ------------------------------------------------- - PR11195: Prevent all nested argument substitution - - Our existing protection only made sure that the first token in a - substitution wasn't a nested substitution. That's not sufficient when - there could be multiple tokens involved. This patch makes sure that no - nested tokens are ever allowed to be argument substitutions. - - This also adds a cursor_suspended_line/column and resets the main - cursor_line/column to the beginning of the substitution, so errors will - point a little closer to the right place. - -diff --git a/parse.cxx b/parse.cxx -index edb1927..2688d6d 100644 ---- a/parse.cxx -+++ b/parse.cxx -@@ -632,7 +632,8 @@ parser::peek_kw (std::string const & kw) - - lexer::lexer (istream& input, const string& in, systemtap_session& s): - input_name (in), input_pointer (0), input_end (0), -- cursor_suspend_count(0), cursor_line (1), cursor_column (1), -+ cursor_suspend_count(0), cursor_suspend_line (1), cursor_suspend_column (1), -+ cursor_line (1), cursor_column (1), - session(s), current_file (0) - { - getline(input, input_contents, '\0'); -@@ -693,9 +694,15 @@ lexer::input_get () - ++input_pointer; - - if (cursor_suspend_count) -- // Track effect of input_put: preserve previous cursor/line_column -- // until all of its characters are consumed. -- cursor_suspend_count --; -+ { -+ // Track effect of input_put: preserve previous cursor/line_column -+ // until all of its characters are consumed. -+ if (--cursor_suspend_count == 0) -+ { -+ cursor_line = cursor_suspend_line; -+ cursor_column = cursor_suspend_column; -+ } -+ } - else - { - // update source cursor -@@ -714,12 +721,16 @@ lexer::input_get () - - - void --lexer::input_put (const string& chars) -+lexer::input_put (const string& chars, const token* t) - { - size_t pos = input_pointer - input_contents.data(); - // clog << "[put:" << chars << " @" << pos << "]"; - input_contents.insert (pos, chars); - cursor_suspend_count += chars.size(); -+ cursor_suspend_line = cursor_line; -+ cursor_suspend_column = cursor_column; -+ cursor_line = t->location.line; -+ cursor_column = t->location.column; - input_pointer = input_contents.data() + pos; - input_end = input_contents.data() + input_contents.size(); - } -@@ -731,19 +742,11 @@ lexer::scan (bool wildcard) - token* n = new token; - n->location.file = current_file; - -- unsigned semiskipped_p = 0; -- -- skip: -+skip: -+ bool suspended = (cursor_suspend_count > 0); - n->location.line = cursor_line; - n->location.column = cursor_column; - -- semiskip: -- if (semiskipped_p > 1) -- { -- input_get (); -- throw parse_error ("invalid nested substitution of command line arguments"); -- } -- - int c = input_get(); - // clog << "{" << (char)c << (char)c2 << "}"; - if (c < 0) -@@ -762,38 +765,41 @@ lexer::scan (bool wildcard) - // characters; @1..@999 are quoted/escaped as strings. - // $# and @# expand to the number of arguments, similarly - // raw or quoted. -- if ((c == '$' || c == '@') && -- (c2 == '#')) -+ if ((c == '$' || c == '@') && (c2 == '#')) - { -+ n->content.push_back (c); -+ n->content.push_back (c2); - input_get(); // swallow '#' -- stringstream converter; -- converter << session.args.size (); -- if (c == '$') input_put (converter.str()); -- else input_put (lex_cast_qstring (converter.str())); -- semiskipped_p ++; -- goto semiskip; -+ if (suspended) -+ throw parse_error ("invalid nested substitution of command line arguments", n); -+ size_t num_args = session.args.size (); -+ input_put ((c == '$') ? lex_cast (num_args) : lex_cast_qstring (num_args), n); -+ n->content.clear(); -+ goto skip; - } -- else if ((c == '$' || c == '@') && -- (isdigit (c2))) -+ else if ((c == '$' || c == '@') && (isdigit (c2))) - { -+ n->content.push_back (c); - unsigned idx = 0; - do - { - input_get (); - idx = (idx * 10) + (c2 - '0'); -+ n->content.push_back (c2); - c2 = input_peek (); - } while (c2 > 0 && - isdigit (c2) && - idx <= session.args.size()); // prevent overflow -+ if (suspended) -+ throw parse_error ("invalid nested substitution of command line arguments", n); - if (idx == 0 || - idx-1 >= session.args.size()) - throw parse_error ("command line argument index " + lex_cast(idx) - + " out of range [1-" + lex_cast(session.args.size()) + "]", n); -- string arg = session.args[idx-1]; -- if (c == '$') input_put (arg); -- else input_put (lex_cast_qstring (arg)); -- semiskipped_p ++; -- goto semiskip; -+ const string& arg = session.args[idx-1]; -+ input_put ((c == '$') ? arg : lex_cast_qstring (arg), n); -+ n->content.clear(); -+ goto skip; - } - - else if (isalpha (c) || c == '$' || c == '@' || c == '_' || -diff --git a/parse.h b/parse.h -index 5587586..0ff8664 100644 ---- a/parse.h -+++ b/parse.h -@@ -79,12 +79,14 @@ public: - private: - inline int input_get (); - inline int input_peek (unsigned n=0); -- void input_put (const std::string&); -+ void input_put (const std::string&, const token*); - std::string input_name; - std::string input_contents; - const char *input_pointer; // index into input_contents - const char *input_end; - unsigned cursor_suspend_count; -+ unsigned cursor_suspend_line; -+ unsigned cursor_suspend_column; - unsigned cursor_line; - unsigned cursor_column; - systemtap_session& session; -diff --git a/testsuite/parseko/preprocess16.stp b/testsuite/parseko/preprocess16.stp -new file mode 100755 -index 0000000..364bad6 ---- /dev/null -+++ b/testsuite/parseko/preprocess16.stp -@@ -0,0 +1,4 @@ -+#! /bin/sh -+ -+# recursive after the first token (PR11195) -+stap -p1 -e 'probe begin {$1}' 'x $1' diff --git a/systemtap-xmlto-fop.diff b/systemtap-xmlto-fop.diff index 3558809..033f8fb 100644 --- a/systemtap-xmlto-fop.diff +++ b/systemtap-xmlto-fop.diff @@ -4,14 +4,14 @@ --- a/doc/SystemTap_Tapset_Reference/Makefile.am +++ b/doc/SystemTap_Tapset_Reference/Makefile.am -@@ -43,7 +43,9 @@ stamp-htmldocs: tapsets.xml +@@ -34,7 +34,9 @@ # bump up the allocated space so "xmlto pdf" works tapsets.pdf: tapsets.xml -- env pool_size=2000000 hash_extra=2000000 xmlto $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 -+# env pool_size=2000000 hash_extra=2000000 xmlto $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 +- env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml ++# env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml + xmlto fo tapsets.xml + fop tapsets.fo tapsets.pdf stamp-mandocs: tapsets.xml - xmlto $(XMLTOMANPARAMS) man -o man3 tapsets.xml >/dev/null 2>&1 + xmlto man -o man3 tapsets.xml diff --git a/systemtap.changes b/systemtap.changes index e1bf13e..94c39a9 100644 --- a/systemtap.changes +++ b/systemtap.changes @@ -1,16 +1,3 @@ -------------------------------------------------------------------- -Thu Mar 11 23:56:17 UTC 2010 - tonyj@novell.com - -- Add dependancies for systemtap shell scripts (coreutils, zip, avahi) - -------------------------------------------------------------------- -Thu Mar 11 22:47:15 UTC 2010 - tonyj@novell.com - -- Update to version 1.1 -- Fixes for CVE-2009-4273 (second part, also known as CVE-2010-0412) and - CVE-2010-0411. -- Fix parsing error (systemtap-prevent-nested-arg.diff) - ------------------------------------------------------------------- Wed Dec 2 23:51:24 UTC 2009 - tonyj@novell.com diff --git a/systemtap.spec b/systemtap.spec index d5ad021..013bca5 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -1,5 +1,5 @@ # -# spec file for package systemtap (Version 1.1) +# spec file for package systemtap (Version 1.0) # # Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. # @@ -23,7 +23,7 @@ BuildRequires: gcc-c++ glib2-devel libcap-devel libebl-devel pkg-config sqlite- BuildRequires: mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools %define use_snapshot 0 License: GPLv2+ -Version: 1.1 +Version: 1.0 Release: 1 Summary: Instrumentation System Group: Development/Tools/Debuggers @@ -35,15 +35,12 @@ Url: http://sourceware.org/systemtap/ %else %define package_version %{version} %endif -Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 -# need -docdir patch even though docs are packaged by systemtap-docs.spec -# so that they are installed into directories matching below rm -rf's -Patch1: systemtap-docdir-fix.diff -Patch2: systemtap-ioblock-suse-kernel-fix.diff -Patch3: systemtap-CVE-2009-4273.diff -Patch4: systemtap-CVE-2010-0411.diff -Patch5: systemtap-prevent-nested-arg.diff - +Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 +Patch: systemtap-docdir-fix.diff +Patch2: systemtap-ioblock-suse-kernel-fix.diff +Patch3: systemtap-CVE-limit-dwarf-expression-stack-size.patch +Patch4: systemtap-CVE-limit-printf-arguments.patch +Patch5: systemtap-CVE-unwind-table-size-checks.patch Requires: libebl1 Requires: %{name}-runtime = %{version}-%{release} BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -85,8 +82,6 @@ License: GPLv2+ Group: Development/Tools/Debuggers Summary: Systemtap client Requires: %{name}-runtime = %{version}-%{release} -# dependancies for systemtap shell scripts -Requires: coreutils avahi avahi-utils mozilla-nss-tools zip unzip %description client SystemTap is an instrumentation system for systems running Linux 2.6. @@ -106,8 +101,6 @@ License: GPLv2+ Group: Development/Tools/Debuggers Summary: Systemtap server Requires: %{name} = %{version}-%{release} -# dependancies for systemtap shell scripts -Requires: coreutils avahi avahi-utils mozilla-nss-tools zip unzip %description server SystemTap is an instrumentation system for systems running Linux 2.6. @@ -147,7 +140,7 @@ Authors: %else %setup -n %{name}-%{package_version} -q %endif -%patch1 -p1 +%patch -p1 %patch2 -p1 %patch3 -p1 %patch4 -p1 @@ -159,19 +152,16 @@ autoreconf -fi make %{?jobs:-j %jobs} %install +%if %suse_version < 1030 +# workaround for old autoconf +export MKDIR_P="mkdir -p" +%endif %makeinstall -# XXX -rm -f $RPM_BUILD_ROOT/usr/lib/systemtap/stap-server-request -# README, AUTHORS, NEWS, man3 and all examples packaged by systemtap-docs -# COPYING needs to stay in main for GPL -rm -rf $RPM_BUILD_ROOT%{_docdir}/systemtap/ +mkdir -p $RPM_BUILD_ROOT/var/cache/systemtap +# doc subpackage is built separetely +# cp README AUTHORS NEWS COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ +rm -rf $RPM_BUILD_ROOT%{_docdir}/systemtap rm -rf $RPM_BUILD_ROOT%{_mandir}/man3 -mkdir -p $RPM_BUILD_ROOT%{_docdir}/systemtap/ -cp COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ -mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/cache/systemtap -mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/systemtap -mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/log -touch $RPM_BUILD_ROOT%{_localstatedir}/log/stap-server.log %clean rm -rf ${RPM_BUILD_ROOT} @@ -180,51 +170,37 @@ rm -rf ${RPM_BUILD_ROOT} %defattr(-,root,root) %{_bindir}/stap %{_mandir}/man1/* -%dir %{_datadir}/%{name} -%{_datadir}/%{name}/runtime -%{_datadir}/%{name}/tapset -#packaged by systemtap-initscript in upstream -%dir %{_localstatedir}/cache/systemtap -%dir %{_localstatedir}/run/systemtap +%{_datadir}/systemtap +%dir %attr(0755,root,root) /var/cache/systemtap %files runtime %defattr(-,root,root) -%doc %{_docdir}/systemtap %{_bindir}/staprun %{_bindir}/stap-report -%{_bindir}/stap-authorize-signing-cert -%dir %{_libexecdir}/%{name} -%{_libexecdir}/%{name}/stapio -%{_libexecdir}/%{name}/stap-env -%{_libexecdir}/%{name}/stap-authorize-cert -%{_mandir}/man8/staprun.8* -%{_mandir}/man8/stap-authorize-signing-cert.8* +%{_libexecdir}/systemtap +%{_mandir}/man8/staprun.* %files client %defattr(-,root,root) -%defattr(-,root,root) %{_bindir}/stap-client -%{_bindir}/stap-authorize-server-cert -%{_libexecdir}/%{name}/stap-find-servers -%{_libexecdir}/%{name}/stap-client-connect -%{_mandir}/man8/stap-client.8* -%{_mandir}/man8/stap-authorize-server-cert.8* +%{_bindir}/stap-find-servers +%{_bindir}/stap-find-or-start-server +%{_bindir}/stap-start-server +%{_bindir}/stap-client-connect +%{_bindir}/stap-env %files server %defattr(-,root,root) -%{_bindir}/stap-authorize-server-cert %{_bindir}/stap-server -%{_libexecdir}/%{name}/stap-serverd -%{_libexecdir}/%{name}/stap-start-server -%{_libexecdir}/%{name}/stap-find-servers -%{_libexecdir}/%{name}/stap-find-or-start-server -%{_libexecdir}/%{name}/stap-stop-server -%{_libexecdir}/%{name}/stap-gen-cert -%{_libexecdir}/%{name}/stap-server-connect -%{_libexecdir}/%{name}/stap-sign-module -%{_mandir}/man8/stap-server.8* -%{_mandir}/man8/stap-authorize-server-cert.8* -%ghost %{_localstatedir}/log/stap-server.log +%{_bindir}/stap-serverd +%{_bindir}/stap-start-server +%{_bindir}/stap-stop-server +%{_bindir}/stap-server-connect +%{_bindir}/stap-authorize* +%{_bindir}/stap-env +%{_bindir}/stap-gen-cert +%{_bindir}/stap-sign-module +%{_mandir}/man8/stap-server.* %files sdt-devel %defattr(-,root,root) From af8494b7bc98284c3f2e257ba12d94cc402dc0a810524e4571fb3cabd71ff9fc Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Wed, 21 Jul 2010 13:53:52 +0000 Subject: [PATCH 6/8] Accepting request 43603 from home:vuntz:branches:devel:tools Copy from home:vuntz:branches:devel:tools/systemtap via accept of submit request 43603 revision 2. Request was accepted with message: Reviewed ok OBS-URL: https://build.opensuse.org/request/show/43603 OBS-URL: https://build.opensuse.org/package/show/devel:tools/systemtap?expand=0&rev=12 --- ready | 0 systemtap-1.0.tar.bz2 | 3 - systemtap-1.1.tar.bz2 | 3 + systemtap-CVE-2009-4273.diff | 925 ++++++++++++++++++ systemtap-CVE-2010-0411.diff | 187 ++++ ...VE-limit-dwarf-expression-stack-size.patch | 135 --- systemtap-CVE-limit-printf-arguments.patch | 75 -- systemtap-CVE-unwind-table-size-checks.patch | 193 ---- systemtap-docdir-fix.diff | 17 +- systemtap-docs.changes | 5 + systemtap-docs.spec | 21 +- systemtap-ioblock-suse-kernel-fix.diff | 12 +- systemtap-prevent-nested-arg.diff | 182 ++++ systemtap-xmlto-fop.diff | 8 +- systemtap.changes | 19 + systemtap.spec | 93 +- 16 files changed, 1411 insertions(+), 467 deletions(-) delete mode 100644 ready delete mode 100644 systemtap-1.0.tar.bz2 create mode 100644 systemtap-1.1.tar.bz2 create mode 100644 systemtap-CVE-2009-4273.diff create mode 100644 systemtap-CVE-2010-0411.diff delete mode 100644 systemtap-CVE-limit-dwarf-expression-stack-size.patch delete mode 100644 systemtap-CVE-limit-printf-arguments.patch delete mode 100644 systemtap-CVE-unwind-table-size-checks.patch create mode 100644 systemtap-prevent-nested-arg.diff diff --git a/ready b/ready deleted file mode 100644 index 473a0f4..0000000 diff --git a/systemtap-1.0.tar.bz2 b/systemtap-1.0.tar.bz2 deleted file mode 100644 index 54bc50d..0000000 --- a/systemtap-1.0.tar.bz2 +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9a942ba85d6360023e6f8503a8dd4c8493d16b17cb474cc8f0ad5a50cec3607a -size 1205746 diff --git a/systemtap-1.1.tar.bz2 b/systemtap-1.1.tar.bz2 new file mode 100644 index 0000000..073b472 --- /dev/null +++ b/systemtap-1.1.tar.bz2 @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1d620a9861cd7c9609fb8012faf20eafb632f3f3a919bf0c08bec3a14924e3a2 +size 1293846 diff --git a/systemtap-CVE-2009-4273.diff b/systemtap-CVE-2009-4273.diff new file mode 100644 index 0000000..005f70a --- /dev/null +++ b/systemtap-CVE-2009-4273.diff @@ -0,0 +1,925 @@ +Subject: VUL-0: systemtap-server code exec +References: bnc#574243 +Signed-Off-By: Tony Jones + +Fix remaining portions of this CVE (part2) still present post release-1.1 +This second part is also referred to as CVE-2010-0412 + +Covers cases such as stap-client -B CC=/bin/rm CFLAGS=/ ... where the +execution is done by make + + + +commit b75067caf1bb416af21473e40c917d953531e9f9 +Author: Dave Brolley +Date: Mon Jan 18 11:56:13 2010 -0500 + + Correct client-side quoting issues discovered by fche during the server-side reimplementation. + + Also add the test cases to the test suite. + +commit 241443ad36a5a2cacb9e8e6f12f808d304835f2a +Author: Dave Brolley +Date: Tue Feb 2 08:26:01 2010 -0500 + + PR 11105: Remaining client-side problems: + + stap-client: Correct handling of embedded newlines in arguments. + server_args.exp: Add additional cases discovered by fche and by fuzzing. + +commit 4240be911e37b817727ecb33f321f0ea389ede61 +Author: Dave Brolley +Date: Mon Feb 15 15:01:28 2010 -0500 + + Don't pass client-only options to the server. + + Also correct parsing of the --server option. + +commit d2334a2233f4efd055dab021c603f7c046730a66 +Author: Dave Brolley +Date: Tue Feb 2 14:08:31 2010 -0500 + + Compile server logging and robustness. + + Log certificate location and status when starting server. + Additional care in handling arguments in stap-serverd. + New test case discovered by fuzzing added and fixed. + +commit c0d1b5a004b9949bb455b7dbe17b335b7cab9ead +Author: Frank Ch. Eigler +Date: Fri Feb 12 10:25:43 2010 -0500 + + PR11105 part 2: tighten constraints on stap-server parameters passed to make + + * util.h, util.cxx (assert_match_regexp): New function. + * main.cxx (main): Constrain -R, -r, -a, -D, -S, -q, -B flags. + * stap-serverd (listen): Harden stap-server-connect with ulimit/loop. + * testsuite/systemtap.server/{client,server}_args.exp: Revised. + +commit cc9e5488d82b728e568bca1f8d6094856fc8e641 +Author: Frank Ch. Eigler +Date: Fri Feb 12 10:39:58 2010 -0500 + + PR11105 part 2a, fix buggy \\. in -r option regexp + +--- + main.cxx | 24 ++-- + stap-client | 151 +++++++++++++++++------------ + stap-gen-cert | 43 ++++---- + stap-serverd | 40 +++++-- + testsuite/systemtap.server/client_args.exp | 28 ++--- + testsuite/systemtap.server/hello.stp | 2 + testsuite/systemtap.server/server_args.exp | 49 +++++---- + util.cxx | 36 ++++++ + util.h | 2 + 9 files changed, 238 insertions(+), 137 deletions(-) + +--- a/main.cxx ++++ b/main.cxx +@@ -57,7 +57,7 @@ version () + << "SystemTap translator/driver " + << "(version " << VERSION << "/" << dwfl_version (NULL) + << " " << GIT_MESSAGE << ")" << endl +- << "Copyright (C) 2005-2009 Red Hat, Inc. and others" << endl ++ << "Copyright (C) 2005-2010 Red Hat, Inc. and others" << endl + << "This is free software; see the source for copying conditions." << endl; + } + +@@ -670,12 +670,12 @@ main (int argc, char * const argv []) + break; + + case 'o': ++ // NB: client_options not a problem, since pass 1-4 does not use output_file. + s.output_file = string (optarg); + break; + + case 'R': +- if (client_options) +- client_options_disallowed += client_options_disallowed.empty () ? "-R" : ", -R"; ++ if (client_options) { cerr << "ERROR: -R invalid with --client-options" << endl; usage(s,1); } + s.runtime_path = string (optarg); + break; + +@@ -684,6 +684,7 @@ main (int argc, char * const argv []) + client_options_disallowed += client_options_disallowed.empty () ? "-m" : ", -m"; + s.module_name = string (optarg); + save_module = true; ++ // XXX: convert to assert_regexp_match() + { + string::size_type len = s.module_name.length(); + +@@ -728,15 +729,14 @@ main (int argc, char * const argv []) + break; + + case 'r': +- if (client_options) +- client_options_disallowed += client_options_disallowed.empty () ? "-r" : ", -r"; ++ if (client_options) // NB: no paths! ++ assert_regexp_match("-r parameter from client", optarg, "^[a-z0-9_.-]+$"); + setup_kernel_release(s, optarg); + break; + + case 'a': +- if (client_options) +- client_options_disallowed += client_options_disallowed.empty () ? "-a" : ", -a"; +- s.architecture = string(optarg); ++ assert_regexp_match("-a parameter", optarg, "^[a-z0-9_-]+$"); ++ s.architecture = string(optarg); + break; + + case 'k': +@@ -783,16 +783,19 @@ main (int argc, char * const argv []) + break; + + case 'D': ++ assert_regexp_match ("-D parameter", optarg, "^[a-z_][a-z_0-9]*(=[a-z_0-9]+)?$"); + if (client_options) + client_options_disallowed += client_options_disallowed.empty () ? "-D" : ", -D"; + s.macros.push_back (string (optarg)); + break; + + case 'S': ++ assert_regexp_match ("-S parameter", optarg, "^[0-9]+(,[0-9]+)?$"); + s.size_option = string (optarg); + break; + + case 'q': ++ if (client_options) { cerr << "ERROR: -q invalid with --client-options" << endl; usage(s,1); } + s.tapset_compile_coverage = true; + break; + +@@ -823,9 +826,8 @@ main (int argc, char * const argv []) + break; + + case 'B': +- if (client_options) +- client_options_disallowed += client_options_disallowed.empty () ? "-B" : ", -B"; +- s.kbuildflags.push_back (string (optarg)); ++ if (client_options) { cerr << "ERROR: -B invalid with --client-options" << endl; usage(s,1); } ++ s.kbuildflags.push_back (string (optarg)); + break; + + case 0: +--- a/stap-client ++++ b/stap-client +@@ -2,7 +2,7 @@ + + # Compile server client for systemtap + # +-# Copyright (C) 2008, 2009, 2010 Red Hat Inc. ++# Copyright (C) 2008-2010 Red Hat Inc. + # + # This file is part of systemtap, and is free software. You can + # redistribute it and/or modify it under the terms of the GNU General +@@ -84,34 +84,34 @@ function parse_options { + # Each command line argument will be written to its own file within the + # request package. + argc=1 ++ packed_options='-' + arg_subst= + + while test $# != 0 + do + advance=0 + dash_seen=0 ++ client_arg=0 + + # Start of a new token. + first_token="$1" + until test $advance != 0 + do + # Identify the next option +- first_char=`expr "$first_token" : '\(.\).*'` ++ first_char="${first_token:0:1}" + second_char= + if test $dash_seen = 0; then + if test "$first_char" = "-"; then + if test "$first_token" != "-"; then + # It's not a lone dash, so it's an option. + # Is it a long option (i.e. --option)? +- second_char=`expr "$first_token" : '.\(.\).*'` ++ second_char="${first_token:1:1}" + if test "X$second_char" = "X-"; then +- long_option=`expr "$first_token" : '--\(.*\)=.*'` +- test "X$long_option" != "X" || long_option=`expr "$first_token" : '--\(.*\)'` +- case $long_option in +- ssl) ++ case "$first_token" in ++ --ssl=*) + process_ssl "$first_token" + ;; +- server) ++ --server=*) + process_server "$first_token" + ;; + *) +@@ -123,9 +123,9 @@ function parse_options { + fi + # It's not a lone dash, or a long option, so it's a short option string. + # Remove the dash. +- first_token=`expr "$first_token" : '-\(.*\)'` ++ first_token="${first_token:1}" + dash_seen=1 +- first_char=`expr "$first_token" : '\(.\).*'` ++ first_char="${first_token:0:1}" + fi + fi + if test $dash_seen = 0; then +@@ -145,69 +145,69 @@ function parse_options { + # We are at the start of an option. Look at the first character. + case $first_char in + a) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_a "$stap_arg" + ;; + B) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + c) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_c "$stap_arg" + ;; + D) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + e) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_e "$stap_arg" + ;; + I) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_I "$stap_arg" + ;; + k) + keep_temps=1 + ;; + l) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + p_phase=2 + ;; + L) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + p_phase=2 + ;; + m) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_m "$stap_arg" + ;; + o) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_o "$stap_arg" + ;; + p) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_p "$stap_arg" + ;; + r) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_r "$stap_arg" + ;; + R) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + process_R "$stap_arg" + ;; + s) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + S) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + v) + v_level=$(($v_level + 1)) + ;; + x) +- get_arg $first_token "$2" ++ get_arg "$first_token" "$2" + ;; + *) + # An unknown or unimportant flag. +@@ -216,7 +216,7 @@ function parse_options { + + if test $advance = 0; then + # Just another flag character. Consume it. +- first_token=`expr "$first_token" : '.\(.*\)'` ++ first_token="${first_token:1}" + if test "X$first_token" = "X"; then + advance=$(($advance + 1)) + fi +@@ -224,9 +224,19 @@ function parse_options { + done + + # Consume the arguments we just processed. +- while test $advance != 0 +- do +- # Place the argument is a numbered file within our temp ++ while test $advance != 0; do ++ # Does the final argument file contain a client-side file ++ # name which must be changed to a server-side name? ++ local arg ++ if test "X$arg_subst" != "X" -a $advance = 1; then ++ arg="$arg_subst" ++ arg_subst= ++ else ++ arg="$1" ++ fi ++ ++ # If it's not client-only argument, ++ # place the argument in a numbered file within our temp + # directory. + # o We don't write a newline at the end, since newline could be + # part of the argument. +@@ -234,20 +244,16 @@ function parse_options { + # in order to avoid having 'echo' interpret the output as + # its own option. We then remove the X. + # There must be a better way. +- echo -n "X$1" > "$tmpdir_client/argv$argc" +- sed -i "s|^X||" "$tmpdir_client/argv$argc" +- +- # Does the final argument file contain client-side data +- # which must be changed to server-side data? +- if test "X$arg_subst" != "X" -a $advance = 1; then +- sed -i "s|$stap_arg|$arg_subst|" "$tmpdir_client/argv$argc" +- arg_subst= ++ if test $client_arg = 0; then ++ echo -n "X$arg" > "$tmpdir_client/argv$argc" ++ sed -i "s|^X||" "$tmpdir_client/argv$argc" ++ argc=$(($argc + 1)) + fi + + # Get the next argument. + shift +- argc=$(($argc + 1)) + advance=$(($advance - 1)) ++ packed_options='-' + done + done + +@@ -256,7 +262,8 @@ function parse_options { + if test "X$script_file" != "X"; then + local local_name + if test "$script_file" != "-"; then +- local_name=`generate_client_temp_name "$script_file"` ++ generate_client_temp_name "$script_file" ++ local_name="$client_temp_name" + else + local_name="-" + fi +@@ -277,8 +284,9 @@ function parse_options { + # Collect an argument to the given option + function get_arg { + # Remove first character. +- local opt=`expr "$1" : '\(.\).*'` +- local first=`expr "$1" : '.\(.*\)'` ++ local opt="${1:0:1}" ++ local first="${1:1}" ++ packed_options="${packed_options}$opt" + + # Advance to the next token, if the first one is exhausted. + if test "X$first" = "X"; then +@@ -294,7 +302,8 @@ function get_arg { + # + # Process the --ssl option. + function process_ssl { +- local db=`expr "$1" : '--ssl=\(.*\)'` ++ client_arg=1 ++ local db="${1:6}" + + test "X$db" != "X" || \ + fatal "Missing argument to --ssl" +@@ -308,7 +317,8 @@ function process_ssl { + # + # Process the --server option. + function process_server { +- local spec=`expr "$1" : '--server=\(.*\)'` ++ client_arg=1 ++ local spec="${1:9}" + + test "X$spec" != "X" || \ + fatal "Missing argument to --server" +@@ -335,12 +345,19 @@ function process_e { + fi + } + +-# function: process_I ARGUMENT ++# function: process_I ARGUMENT ORIGINAL_ARGUMENT + # + # Process the -I flag. + function process_I { + test "X$1" = "X" && return +- arg_subst=tapsets/`include_file_or_directory tapsets "$1"` ++ test "${1:0:1}" = " ++" && return ++ include_file_or_directory tapsets "$1" ++ if test $advance = 1; then ++ arg_subst="${packed_options}tapsets/$included_name" ++ else ++ arg_subst="tapsets/$included_name" ++ fi + } + + # function: process_m ARGUMENT +@@ -369,7 +386,7 @@ function process_p { + # + # Process the -r flag. + function process_r { +- local first_char=`expr "$1" : '\(.\).*'` ++ local first_char="${1:0:1}" + + if test "$first_char" = "/"; then # fully specified path + kernel_build_tree="$1" +@@ -402,23 +419,34 @@ function process_a { + fi + } + +-# function: process_R ARGUMENT ++# function: process_R ARGUMENT ORIGINAL_ARGUMENT + # + # Process the -R flag. + function process_R { + test "X$1" = "X" && return +- arg_subst=runtime/`include_file_or_directory runtime "$1"` ++ test "${1:0:1}" = " ++" && return ++ include_file_or_directory runtime "$1" ++ if test $advance = 1; then ++ arg_subst="${packed_options}runtime/$included_name" ++ else ++ arg_subst="runtime/$included_name" ++ fi + } + + # function: include_file_or_directory PREFIX NAME + # + # Include the given file or directory in the client's temporary +-# tree to be sent to the server. ++# tree to be sent to the server and save it's name in the variable ++# included_name. We use a global variable instread of echoing the ++# result since the use of `include_file_or_directory` loses a trailing ++# newline. + function include_file_or_directory { + # Add a symbolic link of the named file or directory to our temporary + # directory, but only if the file or directory exists. +- local local_name=`generate_client_temp_name "$2"` +- echo "$local_name" ++ generate_client_temp_name "$2" ++ local local_name="$client_temp_name" ++ included_name="$local_name" + test -e "/$local_name" || return + + local local_dirname=`dirname "$local_name"` +@@ -431,15 +459,20 @@ function include_file_or_directory { + # function: generate_client_temp_name NAME + # + # Generate the name to be used for the given file/directory relative to the +-# client's temporary directory. ++# client's temporary directory and stores it in the variable ++# client_temp_name. We use a global variable instread of echoing the ++# result since the use of `generate_client_temp_name` loses a trailing ++# newline. + function generate_client_temp_name { + # Transform the name into a fully qualified path name +- local full_name=`echo "X$1" | sed "s,^X\\\([^/]\\\),$wd/\\\\1," | sed 's,^X,,'` ++ local full_name="$1" ++ test "${full_name:0:1}" != "/" && full_name="$wd/$full_name" + + # The same name without the initial / or trailing / +- local local_name=`echo "$full_name" | sed 's,^/\(.*\),\1,'` +- local_name=`echo "$local_name" | sed 's,\(.*\)/$,\1,'` +- echo "$local_name" ++ local local_name="${full_name:1}" ++ test "${local_name: -1:1}" = "/" && local_name="${local_name:0:$((${#local_name}-1))}" ++ ++ client_temp_name="$local_name" + } + + # function: create_request +@@ -456,7 +489,7 @@ function create_request { + fatal "Cannot create temporary directory " $tmpdir_client/script + cat > "$tmpdir_client/script/$script_file" + else +- include_file_or_directory script "$script_file" > /dev/null ++ include_file_or_directory script "$script_file" + fi + fi + +@@ -505,7 +538,7 @@ function unpack_response { + # 2) a file called stderr + # 3) a file called rc + # 4) optionally a directory named to match stap?????? +- num_files=`ls $tmpdir_server | wc -l` ++ local num_files=`ls $tmpdir_server | wc -l` + test $num_files = 4 -o $num_files = 3 || \ + fatal "Wrong number of files in server's temp directory" + test -f $tmpdir_server/stdout || \ +--- a/stap-gen-cert ++++ b/stap-gen-cert +@@ -3,7 +3,7 @@ + # Generate a certificate for the systemtap server and add it to the + # database of trusted servers for the client. + # +-# Copyright (C) 2008, 2009 Red Hat Inc. ++# Copyright (C) 2008-2010 Red Hat Inc. + # + # This file is part of systemtap, and is free software. You can + # redistribute it and/or modify it under the terms of the GNU General +@@ -14,61 +14,68 @@ + . ${PKGLIBEXECDIR}stap-env + + # Obtain the certificate database directory name. +-serverdb=$1 ++serverdb="$1" + if test "X$serverdb" = "X"; then +- serverdb=$stap_ssl_db/server ++ serverdb="$stap_ssl_db/server" + fi +-rm -fr $serverdb ++rm -fr "$serverdb" + + # Create the server's certificate database directory. +-if ! mkdir -p -m 755 $serverdb; then ++if ! mkdir -p -m 755 "$serverdb"; then + echo "Unable to create the server certificate database directory: $serverdb" >&2 + exit 1 + fi + + # Create the certificate database password file. Care must be taken + # that this file is only readable by the owner. +-if ! (touch $serverdb/pw && chmod 600 $serverdb/pw); then ++if ! (touch "$serverdb/pw" && chmod 600 "$serverdb/pw"); then + echo "Unable to create the server certificate database password file: $serverdb/pw" >&2 + exit 1 + fi + + # Generate a random password. +-mkpasswd -l 20 > $serverdb/pw 2>/dev/null || \ +-apg -a 1 -n 1 -m 20 -x 20 > $serverdb/pw 2>/dev/null || \ +-(read -n20 password $serverdb/pw) ++mkpasswd -l 20 > "$serverdb/pw" 2>/dev/null || \ ++apg -a 1 -n 1 -m 20 -x 20 > "$serverdb/pw" 2>/dev/null || \ ++(read -n20 password "$serverdb/pw") + + # Generate the server certificate database +-if ! certutil -N -d $serverdb -f $serverdb/pw > /dev/null; then ++if ! certutil -N -d "$serverdb" -f "$serverdb/pw" > /dev/null; then + echo "Unable to initialize the server certificate database directory: $serverdb" >&2 + exit 1 + fi + + # We need some random noise for generating keys +-dd bs=123 count=1 < /dev/urandom > $serverdb/noise 2> /dev/null ++dd bs=123 count=1 < /dev/urandom > "$serverdb/noise" 2> /dev/null + + # Generate a request for the server's certificate. +-certutil -R -d $serverdb -f $serverdb/pw -s "CN=Systemtap Compile Server, OU=Systemtap, O=Red Hat, C=US" -o $serverdb/stap.req -z $serverdb/noise 2> /dev/null +-rm -fr $serverdb/noise ++certutil -R -d "$serverdb" -f "$serverdb/pw" -s "CN=Systemtap Compile Server, OU=Systemtap, O=Red Hat, C=US" \ ++ -o "$serverdb/stap.req" -z "$serverdb/noise" 2> /dev/null ++rm -fr "$serverdb/noise" + + # Create the certificate file first so that it always has the proper access permissions. +-if ! (touch $serverdb/$stap_certfile && chmod 644 $serverdb/$stap_certfile); then ++if ! (touch "$serverdb/$stap_certfile" && chmod 644 "$serverdb/$stap_certfile"); then + echo "Unable to create the server certificate file: $serverdb/$stap_certfile" >&2 + exit 1 + fi + +-# Now generate the actual certificate. +-certutil -C -i $serverdb/stap.req -o $serverdb/$stap_certfile -x -d $serverdb -f $serverdb/pw -5 -8 "$HOSTNAME,localhost" >/dev/null <<-EOF ++# Now generate the actual certificate. Make is valid for 1 year. ++certutil -C -i "$serverdb/stap.req" -o "$serverdb/$stap_certfile" -x -d "$serverdb" \ ++ -f "$serverdb/pw" -v 12 -5 -8 "$HOSTNAME,localhost" >/dev/null <<-EOF + 1 + 3 + 7 + 8 + y + EOF +-rm -fr $serverdb/stap.req ++rm -fr "$serverdb/stap.req" + + # Add the certificate to the server's certificate/key database as a trusted peer, ssl server and object signer +-certutil -A -n stap-server -t "PCu,,PCu" -i $serverdb/$stap_certfile -d $serverdb -f $serverdb/pw ++certutil -A -n stap-server -t "PCu,,PCu" -i "$serverdb/$stap_certfile" -d "$serverdb" -f "$serverdb/pw" + ++# Print some information about the certificate. + echo "Certificate $serverdb/$stap_certfile created and added to database $serverdb" ++certutil -L -d "$serverdb" -n stap-server | \ ++ awk '/Validity|Not After|Not Before/ { print $0 }' | \ ++ sed 's/^ */ /' ++ + exit 0 +--- a/stap-serverd ++++ b/stap-serverd +@@ -70,12 +70,18 @@ function initialization { + -x `which ${stap_exec_prefix}stap-client 2>/dev/null`; then + ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 + fi +- elif ! test -f $stap_ssl_db/client/cert8.db; then +- # If the client's database does not exist, then initialize it with our certificate. +- # Do this only if the client has been installed. +- if test -f `which ${stap_exec_prefix}stap-client` -a \ +- -x `which ${stap_exec_prefix}stap-client`; then +- ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 ++ else ++ echo "Certificate found in database $ssl_db" >> $logfile ++ certutil -L -d "$ssl_db" -n stap-server | \ ++ awk '/Validity|Not After|Not Before/ { print $0 }' | \ ++ sed 's/^ */ /' >> $logfile ++ if ! test -f $stap_ssl_db/client/cert8.db; then ++ # If the client's database does not exist, then initialize it with our certificate. ++ # Do this only if the client has been installed. ++ if test -f `which ${stap_exec_prefix}stap-client 2>/dev/null` -a \ ++ -x `which ${stap_exec_prefix}stap-client 2>/dev/null`; then ++ ${stap_exec_prefix}stap-authorize-server-cert $ssl_db/$stap_certfile >> $logfile 2>&1 ++ fi + fi + fi + fi +@@ -343,11 +349,19 @@ function advertise_presence { + function listen { + # The stap-server-connect program will listen forever + # accepting requests. +- ${stap_pkglibexecdir}stap-server-connect \ +- -p $port -n $nss_cert -d $ssl_db -w $nss_pw \ +- -s "$stap_options" \ +- >> $logfile 2>&1 & +- wait '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 ++ # CVE-2009-4273 ... or at least, until resource limits fire ++ while true; do # NB: loop to avoid DoS by deliberate rlimit-induced halt ++ # NB: impose resource limits in case of mischevious data inducing ++ # too much / long computation ++ (ulimit -f 50000 -s 1000 -t 60 -u 20 -v 500000; ++ exec ${stap_pkglibexecdir}stap-server-connect \ ++ -p $port -n $nss_cert -d $ssl_db -w $nss_pw \ ++ -s "$stap_options") & ++ stap_server_connect_pid=$! ++ wait ++ # NB: avoid superfast spinning in case of a ulimit or other failure ++ sleep 1 ++ done >> $logfile 2>&1 + } + + # function: warning [ MESSAGE ] +@@ -379,8 +393,8 @@ function terminate { + wait '%avahi-publish-service' >> $logfile 2>&1 + + # Kill any running 'stap-server-connect' job. +- kill -s SIGTERM '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 +- wait '%${stap_pkglibexecdir}stap-server-connect' >> $logfile 2>&1 ++ kill -s SIGTERM $stap_server_connect_pid >> $logfile 2>&1 ++ wait $stap_server_connect_pid >> $logfile 2>&1 + + exit + } +--- a/testsuite/systemtap.server/client_args.exp ++++ b/testsuite/systemtap.server/client_args.exp +@@ -5,33 +5,34 @@ set test "Invalid Server Client Argument + set test_file $srcdir/systemtap.server/test.stp + + # Test invalid combinations. +-set error_regexp ".*You can't specify .* when --unprivileged is specified.*" ++set error_regexp ".*(ERROR)|(You can't specify .* when --unprivileged is specified).*" + + set invalid_options [list \ +- "--unprivileged --client-options -a i386" \ + "--unprivileged --client-options -B X=Y" \ + "--unprivileged --client-options -D X=Y" \ + "--unprivileged --client-options -I /tmp" \ + "--unprivileged --client-options -m test" \ + "--unprivileged --client-options -R /tmp" \ +- "--unprivileged --client-options -r [exec uname -r]" \ +- "--unprivileged --client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ +- "--client-options --unprivileged -a i386" \ ++ "--unprivileged --client-options -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ + "--client-options --unprivileged -B X=Y" \ + "--client-options --unprivileged -D X=Y" \ + "--client-options --unprivileged -I /tmp" \ + "--client-options --unprivileged -m test" \ + "--client-options --unprivileged -R /tmp" \ +- "--client-options --unprivileged -r [exec uname -r]" \ +- "--client-options --unprivileged -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ +- "--client-options -a i386 --unprivileged" \ ++ "--client-options --unprivileged -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ + "--client-options -B X=Y --unprivileged" \ + "--client-options -D X=Y --unprivileged" \ + "--client-options -I /tmp --unprivileged" \ + "--client-options -m test --unprivileged" \ + "--client-options -R /tmp --unprivileged" \ +- "--client-options -r [exec uname -r] --unprivileged" \ +- "--client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r] --unprivileged" \ ++ "--client-options -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r] --unprivileged" \ ++ "--client-options -R /path" \ ++ "-D \"foo;bar\"" \ ++ "-D 2=4" \ ++ "-D \"foo;bar\"" \ ++ "--client-options -r /path" \ ++ "-S /path" \ ++ "--client-options -q" \ + ] + + foreach options $invalid_options { +@@ -66,9 +67,8 @@ set valid_options [list \ + "-D X=Y" \ + "-I /tmp" \ + "-m test" \ +- "-R /tmp" \ + "-r [exec uname -r]" \ +- "-a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ ++ "-a i386 -B X=Y -D X=Y -I /tmp -m test -r [exec uname -r]" \ + "--unprivileged" \ + "--unprivileged -a i386" \ + "--unprivileged -B X=Y" \ +@@ -80,13 +80,11 @@ set valid_options [list \ + "--unprivileged -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ + "--client-options" \ + "--client-options -a i386" \ +- "--client-options -B X=Y" \ + "--client-options -D X=Y" \ + "--client-options -I /tmp" \ + "--client-options -m test" \ +- "--client-options -R /tmp" \ + "--client-options -r [exec uname -r]" \ +- "--client-options -a i386 -B X=Y -D X=Y -I /tmp -m test -R /tmp -r [exec uname -r]" \ ++ "--client-options -a i386 -D X=Y -I /tmp -m test -r [exec uname -r]" \ + "--unprivileged --client-options" \ + "--client-options --unprivileged" \ + "--unprivileged -a i386 --client-options" \ +--- a/testsuite/systemtap.server/hello.stp ++++ b/testsuite/systemtap.server/hello.stp +@@ -1,4 +1,4 @@ +-#! stap ++#! stap -p5 + + probe begin + { +--- a/testsuite/systemtap.server/server_args.exp ++++ b/testsuite/systemtap.server/server_args.exp +@@ -40,11 +40,13 @@ proc stap_direct_and_with_client {stap s + # Some messages contain the names of files or directories + # and will be prefixed for the client. + if {[regexp "^ (.*)" $expected_line match data]} { +- if {[regexp "^ tapsets/.*/$data" $line]} { ++ # Special characters in the regexp need to be quoted. ++ regsub -all "\[\"\\\\;\*\]" $data {\\\0} data ++ if {[regexp "^ tapsets.*/$data" $line]} { + incr n + continue + } +- if {[regexp "^ runtime/.*/$data" $line]} { ++ if {[regexp "^ runtime.*/$data" $line]} { + incr n + continue + } +@@ -57,7 +59,9 @@ proc stap_direct_and_with_client {stap s + } + } else { + if {[regexp "^Input file '(.*)' is empty or missing." $expected_line match data]} { +- if {[regexp "^Input file 'script/.*/$data' is empty or missing." $line]} { ++ # Special characters in the regexp need to be quoted. ++ regsub -all "\[\"\\\\;\*\]" $data {\\\0} data ++ if {[regexp "^Input file 'script.*/$data' is empty or missing." $line]} { + incr n + continue + } +@@ -110,21 +114,27 @@ if {[installtest_p]} then { + # for debugging a currently failing case and helps to ensure that previously + # fixed cases do not regress. + set previously_fixed [list \ ++ "-p1 -I=\\w94\nbh -e -Dhfuo0iu7 -c" \ ++ "-p1 -I8o\\2ie -e'1\\ -D\n\" -c" \ ++ "-p1 -Ira\\3;c g -e0fle'qq -Dr/316k\\o8 -cjyoc\n3" \ ++ "-p1 -I6p3 -elc -Dqgsgv' -c" \ ++ "-p1 -I\"vyv;z -ej\"/3 -D/ 01qck\n -c3u55zut" \ ++ "-p1 -I1 -eo9e\nx047q -D9xyefk0a -cvl98/x1'i" \ + "-p1 -c; test.stp" \ +- "-p1 -I4hgy96 -R -e5oo39p -Bile\\vp -Ddx8v -c4;" \ +- "-p1 -I -Repwd9 -esq3wors -Btmk;\\t -Dz -c*eibz8h2e" \ +- "-p1 -I -Ry a -em339db5 -B;ae41428d -Du2;c0ps -ch9o\\" \ +- "-p1 -Ipfjps4 -Rx479 -ebug4dc -Bih;fe2 -Du8vd fvkl -c" \ +- "-p1 -I0\"nspzjyf -R -e5r3up8h -Bgqnyjq6w -Dmi;ojp9m -cx;a2fat" \ +- "-p1 -Iu -R9 -ek7;r -Big -Dcu\"; -c\"hc" \ +- "-p1 -Icd4fidq -Rkj m40mv -edn -B7ria -D;8ha\\cjr -c1*vnq" \ +- "-p1 -I;3 -R3lq;vp -er8e -Bgdqjqdy -D -cb6k29z" \ +- "-p1 -Ircj -R -e -B -D -c\\vmww" \ +- "-p1 -Illc5 -Rug*\\o -e65wof9 -B qr*=x7x5 -D -cgx;" \ +- "-p1 -Iyaj420=3 -R -e\" -Bx68j -D -cd'5mi" \ +- "-p1 -Ir -Rwd8;;sjl -e -Bxh; -D29\\ -cj2szt;4" \ +- "-p1 -Ibno3=b4sk -R*5 -e' -Byl63flos -Dg2-j;e -c2ijx'" \ +- "-p1 -I285v7pl -R9a -eo5\\0 -Bfs* -D86s -c-c*v" \ ++ "-p1 -I4hgy96 -e5oo39p -Ddx8v -c4;" \ ++ "-p1 -I -esq3wors -Dz -c*eibz8h2e" \ ++ "-p1 -I a -em339db5 -Du2;c0ps -ch9o\\" \ ++ "-p1 -Ipfjps4 -ebug4dc -Du8vd fvkl -c" \ ++ "-p1 -I0\"nspzjyf -e5r3up8h -Dmi;ojp9m -cx;a2fat" \ ++ "-p1 -Iu -ek7;r -Dcu\"; -c\"hc" \ ++ "-p1 -Icd4fidq m40mv -edn -D;8ha\\cjr -c1*vnq" \ ++ "-p1 -I;3 -er8e -D -cb6k29z" \ ++ "-p1 -Ircj -e -D -c\\vmww" \ ++ "-p1 -Illc5 -e65wof9 qr*=x7x5 -D -cgx;" \ ++ "-p1 -Iyaj420=3 -e\" -D -cd'5mi" \ ++ "-p1 -Ir -e -D29\\ -cj2szt;4" \ ++ "-p1 -Ibno3=b4sk -e' -Dg2-j;e -c2ijx'" \ ++ "-p1 -I285v7pl -eo5\\0 -D86s -c-c*v" \ + ] + + set i 0 +@@ -140,7 +150,10 @@ foreach options $previously_fixed { + # Generate semi-random arguments containing with potential problem characters. + # Check that running systemtap with the client/server generates output + # comparable to running stap directly. +-set dangerous_options [list "-I" "-R" "-e" "-B" "-D" "-c"] ++set dangerous_options [list "-I" "-e" "-D" "-c" "-S"] ++# NB: Other options could be candidates here, like -r and -B, but ++# there stap-server imposes more restrictions than local stap, so ++# this simple error-matching test cannot use them. + set argchars "0123456789/;*'=-\\\"\n abcdefghijklmnopqrstuvwxyz" + + for {set i 0} {$i < $iterations} {incr i} { +--- a/util.cxx ++++ b/util.cxx +@@ -1,5 +1,5 @@ + // Copyright (C) Andrew Tridgell 2002 (original file) +-// Copyright (C) 2006, 2009 Red Hat Inc. (systemtap changes) ++// Copyright (C) 2006-2010 Red Hat Inc. (systemtap changes) + // + // This program is free software; you can redistribute it and/or + // modify it under the terms of the GNU General Public License as +@@ -19,6 +19,8 @@ + #include "sys/sdt.h" + #include + #include ++#include ++#include + + extern "C" { + #include +@@ -31,6 +33,7 @@ extern "C" { + #include + #include + #include ++#include + } + + using namespace std; +@@ -413,4 +416,35 @@ kill_stap_spawn(int sig) + return spawned_pid ? kill(spawned_pid, sig) : 0; + } + ++ ++void assert_regexp_match (const string& name, const string& value, const string& re) ++{ ++ typedef map cache; ++ static cache compiled; ++ cache::iterator it = compiled.find (re); ++ regex_t* r = 0; ++ if (it == compiled.end()) ++ { ++ r = new regex_t; ++ int rc = regcomp (r, re.c_str(), REG_ICASE|REG_NOSUB|REG_EXTENDED); ++ if (rc) { ++ cerr << "regcomp " << re << " (" << name << ") error rc=" << rc << endl; ++ exit(1); ++ } ++ compiled[re] = r; ++ } ++ else ++ r = it->second; ++ ++ // run regexec ++ int rc = regexec (r, value.c_str(), 0, 0, 0); ++ if (rc) ++ { ++ cerr << "ERROR: Safety pattern mismatch for " << name ++ << " ('" << value << "' vs. '" << re << "') rc=" << rc << endl; ++ exit(1); ++ } ++} ++ ++ + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ +--- a/util.h ++++ b/util.h +@@ -21,7 +21,7 @@ const std::string cmdstr_quoted(const st + std::string git_revision(const std::string& path); + int stap_system(int verbose, const std::string& command); + int kill_stap_spawn(int sig); +- ++void assert_regexp_match (const std::string& name, const std::string& value, const std::string& re); + + // stringification generics + diff --git a/systemtap-CVE-2010-0411.diff b/systemtap-CVE-2010-0411.diff new file mode 100644 index 0000000..59cf89a --- /dev/null +++ b/systemtap-CVE-2010-0411.diff @@ -0,0 +1,187 @@ +Subject: VUL-1: systemtap: DoS issue in __get_argv() function +References: bnc#577382 +Signed-Off-By: Tony Jones + +commit a2d399c87a642190f08ede63dc6fc434a5a8363a +Author: Josh Stone +Date: Thu Feb 4 17:47:31 2010 -0800 + + PR11234: Rewrite __get_argv without embedded-C + + We now implement __get_argv's string building in pure stap script. + Also, every argument is now quoted, which is different than before, but + it's much more robust about handling special characters. + +diff --git a/tapset/aux_syscalls.stp b/tapset/aux_syscalls.stp +index bab0f64..e762b37 100644 +--- a/tapset/aux_syscalls.stp ++++ b/tapset/aux_syscalls.stp +@@ -399,124 +399,53 @@ function __sem_flags:string(semflg:long) + + + /* This function copies an argv from userspace. */ +-function __get_argv:string(a:long, first:long) +-%{ /* pure */ +- char __user *__user *argv = (char __user *__user *)(long)THIS->a; +- char __user *vstr; +- int space, rc, len = MAXSTRINGLEN; +- char *str = THIS->__retvalue; +- char buf[80]; +- char *ptr = buf; +- +- +- if (THIS->first && argv) +- argv++; +- +- while (argv != NULL) { +- if (__stp_get_user (vstr, argv)) +- break; +- +- if (vstr == NULL) +- break; +- +- rc = _stp_strncpy_from_user(buf, vstr, 79); +- if (rc <= 0) +- break; +- +- /* check for whitespace in string */ +- buf[rc] = 0; +- ptr = buf; +- space = 0; +- while (*ptr && rc--) { +- if (isspace(*ptr++)) { +- space = 1; +- break; +- } +- } +- +- if (len != MAXSTRINGLEN && len) { +- *str++=' '; +- len--; +- } +- +- if (space && len) { +- *str++='\"'; +- len--; +- } +- +- rc = strlcpy (str, buf, len); +- str += rc; +- len -= rc; +- +- if (space && len) { +- *str++='\"'; +- len--; +- } +- +- argv++; ++function __get_argv:string(argv:long, first:long) ++{ ++%( CONFIG_64BIT == "y" %? ++ if (first && argv) ++ argv += 8 ++ while (argv) { ++ vstr = user_long(argv) ++ if (!vstr) ++ break ++ if (len) ++ str .= " " ++ str .= user_string_quoted(vstr) ++ ++ newlen = strlen(str) ++ if (newlen == len) ++ break ++ len = newlen ++ argv += 8 + } +- *str = 0; +-%} +-/* This function copies an argv from userspace. */ +-function __get_compat_argv:string(a:long, first:long) +-%{ /* pure */ +-#ifdef CONFIG_COMPAT +- compat_uptr_t __user *__user *argv = (compat_uptr_t __user *__user *)(long)THIS->a; +- compat_uptr_t __user *vstr; +- int space, rc, len = MAXSTRINGLEN; +- char *str = THIS->__retvalue; +- char buf[80]; +- char *ptr = buf; +- +- if (THIS->first && argv) +- argv++; +- +- while (argv != NULL) { +- if (__stp_get_user (vstr, argv)) +- break; +- +- if (vstr == NULL) +- break; +- +- rc = _stp_strncpy_from_user(buf, (char *)vstr, 79); +- if (rc <= 0) +- break; +- +- /* check for whitespace in string */ +- buf[rc] = 0; +- ptr = buf; +- space = 0; +- while (*ptr && rc--) { +- if (isspace(*ptr++)) { +- space = 1; +- break; +- } +- } +- +- if (len != MAXSTRINGLEN && len) { +- *str++=' '; +- len--; +- } +- +- if (space && len) { +- *str++='\"'; +- len--; +- } +- +- rc = strlcpy (str, buf, len); +- str += rc; +- len -= rc; +- +- if (space && len) { +- *str++='\"'; +- len--; +- } + +- argv++; ++ return str ++%: ++ return __get_compat_argv(argv, first) ++%) ++} ++/* This function copies an argv from userspace. */ ++function __get_compat_argv:string(argv:long, first:long) ++{ ++ if (first && argv) ++ argv += 4 ++ while (argv) { ++ vstr = user_int(argv) & 0xffffffff ++ if (!vstr) ++ break ++ if (len) ++ str .= " " ++ str .= user_string_quoted(vstr) ++ ++ newlen = strlen(str) ++ if (newlen == len) ++ break ++ len = newlen ++ argv += 4 + } +- *str = 0; +-#endif +-%} ++ ++ return str ++} + + /* + * Return the symbolic string representation diff --git a/systemtap-CVE-limit-dwarf-expression-stack-size.patch b/systemtap-CVE-limit-dwarf-expression-stack-size.patch deleted file mode 100644 index 4394e4f..0000000 --- a/systemtap-CVE-limit-dwarf-expression-stack-size.patch +++ /dev/null @@ -1,135 +0,0 @@ -From: Jan Lieskovsky -Subject: Three SystemTap-1.0 denial of service issues -References: CVE-2009-2911, BNC#548361 -Upstream: yes - - Three denial of service flaws were found in the SystemTap -instrumentation system of version 1.0, when the --unprivileged mode was -activated: - -b, Kernel stack frame overflow allows local attackers to cause denial -of service via specially-crafted user-provided DWARF information. - -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/systemtap-CVE-limit-printf-arguments.patch b/systemtap-CVE-limit-printf-arguments.patch deleted file mode 100644 index 32041a0..0000000 --- a/systemtap-CVE-limit-printf-arguments.patch +++ /dev/null @@ -1,75 +0,0 @@ -From: Jan Lieskovsky -Subject: Three SystemTap-1.0 denial of service issues -References: CVE-2009-2911, BNC#548361 -Upstream: yes - - Three denial of service flaws were found in the SystemTap -instrumentation system of version 1.0, when the --unprivileged mode was -activated: - -a, Kernel stack overflow allows local attackers to cause denial of service or -execute arbitrary code via long number of parameters, provided to the print* -call. - -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 tmp; - - diff --git a/systemtap-CVE-unwind-table-size-checks.patch b/systemtap-CVE-unwind-table-size-checks.patch deleted file mode 100644 index 408239b..0000000 --- a/systemtap-CVE-unwind-table-size-checks.patch +++ /dev/null @@ -1,193 +0,0 @@ -From: Jan Lieskovsky -Subject: Three SystemTap-1.0 denial of service issues -References: CVE-2009-2911, BNC#548361 -Upstream: yes - - Three denial of service flaws were found in the SystemTap -instrumentation system of version 1.0, when the --unprivileged mode was -activated: - -c, Absent check(s) for the upper bound of the size of the unwind table - and for the upper bound of the size of each of the CIE/CFI records, could - allow an attacker to cause a denial of service (infinite loop). - -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 != ¬_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 == ¬_fde || (ptrType = fde_pointer_type(cie)) < 0) -+ if (cie == NULL || cie == ¬_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 - } - -+// 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/systemtap-docdir-fix.diff b/systemtap-docdir-fix.diff index 9cb4ad9..ecdced0 100644 --- a/systemtap-docdir-fix.diff +++ b/systemtap-docdir-fix.diff @@ -1,3 +1,10 @@ +From: Tony Jones +Subject: change doc install path +References: none +Upstream: never + +SuSE %{_docdir} is /usr/share/doc/packages. Change install locations to match. + --- Makefile.am | 2 +- doc/Makefile.am | 2 +- @@ -7,15 +14,15 @@ --- a/Makefile.am +++ b/Makefile.am -@@ -218,7 +218,7 @@ +@@ -257,7 +257,7 @@ install-data-local: | while read f; do if test -x $$f; then \ i_cmd="$(INSTALL_PROGRAM)"; else \ i_cmd="$(INSTALL_DATA)"; fi; \ - $$i_cmd -D $$f $(DESTDIR)$(docdir)/examples/$$f; done) + $$i_cmd -D $$f $(DESTDIR)$(datadir)/doc/packages/systemtap/examples/$$f; done) test -e $(DESTDIR)$(sysconfdir)/systemtap || mkdir -p $(DESTDIR)$(sysconfdir)/systemtap - - TEST_COV_DIR = coverage + if BUILD_SERVER + test -e $(DESTDIR)$(localstatedir)/run/stap-server || mkdir -p $(DESTDIR)$(localstatedir)/run/stap-server --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -2,7 +2,7 @@ @@ -24,7 +31,7 @@ PDF_FILES = tutorial.pdf langref.pdf -DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap +DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/packages/systemtap - SUBDIRS = SystemTap_Tapset_Reference + SUBDIRS = SystemTap_Tapset_Reference beginners if BUILD_DOCS --- a/doc/SystemTap_Tapset_Reference/Makefile.am @@ -43,7 +50,7 @@ ### --- a/stapex.3stap.in +++ b/stapex.3stap.in -@@ -114,12 +114,12 @@ +@@ -114,12 +114,12 @@ To list the probeable functions and loca .SH MORE EXAMPLES Larger examples, demos and samples can be found in diff --git a/systemtap-docs.changes b/systemtap-docs.changes index 8573048..1a076e3 100644 --- a/systemtap-docs.changes +++ b/systemtap-docs.changes @@ -1,3 +1,8 @@ +------------------------------------------------------------------- +Thu Mar 11 22:49:52 UTC 2010 - tonyj@novell.com + +- Update to version 1.1. See systemtap.changes for full changelog. + ------------------------------------------------------------------- Wed Dec 2 23:52:10 UTC 2009 - tonyj@novell.com diff --git a/systemtap-docs.spec b/systemtap-docs.spec index 35adc8f..61dd589 100644 --- a/systemtap-docs.spec +++ b/systemtap-docs.spec @@ -1,7 +1,7 @@ # -# spec file for package systemtap-docs (Version 1.0) +# spec file for package systemtap-docs (Version 1.1) # -# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -22,13 +22,11 @@ Name: systemtap-docs BuildRequires: gcc-c++ libebl-devel pkg-config # for documents BuildRequires: xmlto -%if %suse_version > 1030 BuildRequires: fop BuildRequires: latex2html -%endif %define use_snapshot 0 License: GPLv2+ -Version: 1.0 +Version: 1.1 Release: 1 Summary: Documents and examples for systemtap Group: Development/Tools/Debuggers @@ -39,7 +37,7 @@ Url: http://sourceware.org/systemtap/ %define package_version %{version} %endif Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 -Patch: systemtap-docdir-fix.diff +Patch1: systemtap-docdir-fix.diff Patch2: systemtap-xmlto-fop.diff BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildArch: noarch @@ -63,10 +61,8 @@ Authors: %else %setup -n systemtap-%{package_version} -q %endif -%patch -p1 -%if %suse_version > 1030 +%patch1 -p1 %patch2 -p1 -%endif %build autoreconf -fi @@ -74,12 +70,9 @@ autoreconf -fi make %{?jobs:-j %jobs} %install -%if %suse_version < 1030 -# workaround for old autoconf -export MKDIR_P="mkdir -p" -%endif %makeinstall doc -cp README AUTHORS NEWS COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ +# COPYING packaged by main spec +cp README AUTHORS NEWS $RPM_BUILD_ROOT%{_docdir}/systemtap/ # remove binaries and runtime stuff rm -rf $RPM_BUILD_ROOT%{_bindir} rm -rf $RPM_BUILD_ROOT%{_libexecdir} diff --git a/systemtap-ioblock-suse-kernel-fix.diff b/systemtap-ioblock-suse-kernel-fix.diff index e274cd6..3f12a69 100644 --- a/systemtap-ioblock-suse-kernel-fix.diff +++ b/systemtap-ioblock-suse-kernel-fix.diff @@ -1,6 +1,10 @@ ---- a/tapset/ioblock.stp-dist 2008-12-05 08:14:19.000000000 +0100 -+++ b/tapset/ioblock.stp 2008-12-05 08:14:27.000000000 +0100 -@@ -122,7 +122,7 @@ +--- + tapset/ioblock.stp | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/tapset/ioblock.stp ++++ b/tapset/ioblock.stp +@@ -118,7 +118,7 @@ probe ioblock.request = kernel.function vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments @@ -9,7 +13,7 @@ hw_segments = $bio->bi_hw_segments %) size = $bio->bi_size -@@ -178,7 +178,7 @@ +@@ -169,7 +169,7 @@ probe ioblock.end = kernel.function("bio vcnt = $bio->bi_vcnt idx = $bio->bi_idx phys_segments = $bio->bi_phys_segments diff --git a/systemtap-prevent-nested-arg.diff b/systemtap-prevent-nested-arg.diff new file mode 100644 index 0000000..8633db2 --- /dev/null +++ b/systemtap-prevent-nested-arg.diff @@ -0,0 +1,182 @@ +From: Josh Stone +Date: Tue Jan 19 15:36:35 2010 -0800 +Git-Repo: git://sources.redhat.com/git/systemtap.git +Git-Commit: 9300f661214a4f4dfac75878485867b30c7db389 +Signed-Off-By: Tony Jones + + tonyj: this fixes parse errors such as: + parse error: expected 'probe', 'global', 'function', or '%{' + saw: identifier '?robe' at + + ------------------------------------------------- + PR11195: Prevent all nested argument substitution + + Our existing protection only made sure that the first token in a + substitution wasn't a nested substitution. That's not sufficient when + there could be multiple tokens involved. This patch makes sure that no + nested tokens are ever allowed to be argument substitutions. + + This also adds a cursor_suspended_line/column and resets the main + cursor_line/column to the beginning of the substitution, so errors will + point a little closer to the right place. + +diff --git a/parse.cxx b/parse.cxx +index edb1927..2688d6d 100644 +--- a/parse.cxx ++++ b/parse.cxx +@@ -632,7 +632,8 @@ parser::peek_kw (std::string const & kw) + + lexer::lexer (istream& input, const string& in, systemtap_session& s): + input_name (in), input_pointer (0), input_end (0), +- cursor_suspend_count(0), cursor_line (1), cursor_column (1), ++ cursor_suspend_count(0), cursor_suspend_line (1), cursor_suspend_column (1), ++ cursor_line (1), cursor_column (1), + session(s), current_file (0) + { + getline(input, input_contents, '\0'); +@@ -693,9 +694,15 @@ lexer::input_get () + ++input_pointer; + + if (cursor_suspend_count) +- // Track effect of input_put: preserve previous cursor/line_column +- // until all of its characters are consumed. +- cursor_suspend_count --; ++ { ++ // Track effect of input_put: preserve previous cursor/line_column ++ // until all of its characters are consumed. ++ if (--cursor_suspend_count == 0) ++ { ++ cursor_line = cursor_suspend_line; ++ cursor_column = cursor_suspend_column; ++ } ++ } + else + { + // update source cursor +@@ -714,12 +721,16 @@ lexer::input_get () + + + void +-lexer::input_put (const string& chars) ++lexer::input_put (const string& chars, const token* t) + { + size_t pos = input_pointer - input_contents.data(); + // clog << "[put:" << chars << " @" << pos << "]"; + input_contents.insert (pos, chars); + cursor_suspend_count += chars.size(); ++ cursor_suspend_line = cursor_line; ++ cursor_suspend_column = cursor_column; ++ cursor_line = t->location.line; ++ cursor_column = t->location.column; + input_pointer = input_contents.data() + pos; + input_end = input_contents.data() + input_contents.size(); + } +@@ -731,19 +742,11 @@ lexer::scan (bool wildcard) + token* n = new token; + n->location.file = current_file; + +- unsigned semiskipped_p = 0; +- +- skip: ++skip: ++ bool suspended = (cursor_suspend_count > 0); + n->location.line = cursor_line; + n->location.column = cursor_column; + +- semiskip: +- if (semiskipped_p > 1) +- { +- input_get (); +- throw parse_error ("invalid nested substitution of command line arguments"); +- } +- + int c = input_get(); + // clog << "{" << (char)c << (char)c2 << "}"; + if (c < 0) +@@ -762,38 +765,41 @@ lexer::scan (bool wildcard) + // characters; @1..@999 are quoted/escaped as strings. + // $# and @# expand to the number of arguments, similarly + // raw or quoted. +- if ((c == '$' || c == '@') && +- (c2 == '#')) ++ if ((c == '$' || c == '@') && (c2 == '#')) + { ++ n->content.push_back (c); ++ n->content.push_back (c2); + input_get(); // swallow '#' +- stringstream converter; +- converter << session.args.size (); +- if (c == '$') input_put (converter.str()); +- else input_put (lex_cast_qstring (converter.str())); +- semiskipped_p ++; +- goto semiskip; ++ if (suspended) ++ throw parse_error ("invalid nested substitution of command line arguments", n); ++ size_t num_args = session.args.size (); ++ input_put ((c == '$') ? lex_cast (num_args) : lex_cast_qstring (num_args), n); ++ n->content.clear(); ++ goto skip; + } +- else if ((c == '$' || c == '@') && +- (isdigit (c2))) ++ else if ((c == '$' || c == '@') && (isdigit (c2))) + { ++ n->content.push_back (c); + unsigned idx = 0; + do + { + input_get (); + idx = (idx * 10) + (c2 - '0'); ++ n->content.push_back (c2); + c2 = input_peek (); + } while (c2 > 0 && + isdigit (c2) && + idx <= session.args.size()); // prevent overflow ++ if (suspended) ++ throw parse_error ("invalid nested substitution of command line arguments", n); + if (idx == 0 || + idx-1 >= session.args.size()) + throw parse_error ("command line argument index " + lex_cast(idx) + + " out of range [1-" + lex_cast(session.args.size()) + "]", n); +- string arg = session.args[idx-1]; +- if (c == '$') input_put (arg); +- else input_put (lex_cast_qstring (arg)); +- semiskipped_p ++; +- goto semiskip; ++ const string& arg = session.args[idx-1]; ++ input_put ((c == '$') ? arg : lex_cast_qstring (arg), n); ++ n->content.clear(); ++ goto skip; + } + + else if (isalpha (c) || c == '$' || c == '@' || c == '_' || +diff --git a/parse.h b/parse.h +index 5587586..0ff8664 100644 +--- a/parse.h ++++ b/parse.h +@@ -79,12 +79,14 @@ public: + private: + inline int input_get (); + inline int input_peek (unsigned n=0); +- void input_put (const std::string&); ++ void input_put (const std::string&, const token*); + std::string input_name; + std::string input_contents; + const char *input_pointer; // index into input_contents + const char *input_end; + unsigned cursor_suspend_count; ++ unsigned cursor_suspend_line; ++ unsigned cursor_suspend_column; + unsigned cursor_line; + unsigned cursor_column; + systemtap_session& session; +diff --git a/testsuite/parseko/preprocess16.stp b/testsuite/parseko/preprocess16.stp +new file mode 100755 +index 0000000..364bad6 +--- /dev/null ++++ b/testsuite/parseko/preprocess16.stp +@@ -0,0 +1,4 @@ ++#! /bin/sh ++ ++# recursive after the first token (PR11195) ++stap -p1 -e 'probe begin {$1}' 'x $1' diff --git a/systemtap-xmlto-fop.diff b/systemtap-xmlto-fop.diff index 033f8fb..3558809 100644 --- a/systemtap-xmlto-fop.diff +++ b/systemtap-xmlto-fop.diff @@ -4,14 +4,14 @@ --- a/doc/SystemTap_Tapset_Reference/Makefile.am +++ b/doc/SystemTap_Tapset_Reference/Makefile.am -@@ -34,7 +34,9 @@ +@@ -43,7 +43,9 @@ stamp-htmldocs: tapsets.xml # bump up the allocated space so "xmlto pdf" works tapsets.pdf: tapsets.xml -- env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml -+# env pool_size=2000000 hash_extra=2000000 xmlto pdf tapsets.xml +- env pool_size=2000000 hash_extra=2000000 xmlto $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 ++# env pool_size=2000000 hash_extra=2000000 xmlto $(XMLTOPDFPARAMS) pdf tapsets.xml >/dev/null 2>&1 + xmlto fo tapsets.xml + fop tapsets.fo tapsets.pdf stamp-mandocs: tapsets.xml - xmlto man -o man3 tapsets.xml + xmlto $(XMLTOMANPARAMS) man -o man3 tapsets.xml >/dev/null 2>&1 diff --git a/systemtap.changes b/systemtap.changes index 94c39a9..a93a6fd 100644 --- a/systemtap.changes +++ b/systemtap.changes @@ -1,3 +1,22 @@ +------------------------------------------------------------------- +Wed Jul 21 12:51:32 CEST 2010 - vuntz@opensuse.org + +- Add python Requires to sdt-devel subpackage since dtrace is a + python script. + +------------------------------------------------------------------- +Thu Mar 11 23:56:17 UTC 2010 - tonyj@novell.com + +- Add dependancies for systemtap shell scripts (coreutils, zip, avahi) + +------------------------------------------------------------------- +Thu Mar 11 22:47:15 UTC 2010 - tonyj@novell.com + +- Update to version 1.1 +- Fixes for CVE-2009-4273 (second part, also known as CVE-2010-0412) and + CVE-2010-0411. +- Fix parsing error (systemtap-prevent-nested-arg.diff) + ------------------------------------------------------------------- Wed Dec 2 23:51:24 UTC 2009 - tonyj@novell.com diff --git a/systemtap.spec b/systemtap.spec index 013bca5..eb4a29b 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -1,7 +1,7 @@ # -# spec file for package systemtap (Version 1.0) +# spec file for package systemtap (Version 1.1) # -# Copyright (c) 2009 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2010 SUSE LINUX Products GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -23,7 +23,7 @@ BuildRequires: gcc-c++ glib2-devel libcap-devel libebl-devel pkg-config sqlite- BuildRequires: mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools %define use_snapshot 0 License: GPLv2+ -Version: 1.0 +Version: 1.1 Release: 1 Summary: Instrumentation System Group: Development/Tools/Debuggers @@ -36,11 +36,14 @@ Url: http://sourceware.org/systemtap/ %define package_version %{version} %endif Source: ftp://sources.redhat.com/pub/systemtap/snapshots/systemtap-%{package_version}.tar.bz2 -Patch: systemtap-docdir-fix.diff +# need -docdir patch even though docs are packaged by systemtap-docs.spec +# so that they are installed into directories matching below rm -rf's +Patch1: systemtap-docdir-fix.diff Patch2: systemtap-ioblock-suse-kernel-fix.diff -Patch3: systemtap-CVE-limit-dwarf-expression-stack-size.patch -Patch4: systemtap-CVE-limit-printf-arguments.patch -Patch5: systemtap-CVE-unwind-table-size-checks.patch +Patch3: systemtap-CVE-2009-4273.diff +Patch4: systemtap-CVE-2010-0411.diff +Patch5: systemtap-prevent-nested-arg.diff + Requires: libebl1 Requires: %{name}-runtime = %{version}-%{release} BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -82,6 +85,8 @@ License: GPLv2+ Group: Development/Tools/Debuggers Summary: Systemtap client Requires: %{name}-runtime = %{version}-%{release} +# dependancies for systemtap shell scripts +Requires: coreutils avahi avahi-utils mozilla-nss-tools zip unzip %description client SystemTap is an instrumentation system for systems running Linux 2.6. @@ -101,6 +106,8 @@ License: GPLv2+ Group: Development/Tools/Debuggers Summary: Systemtap server Requires: %{name} = %{version}-%{release} +# dependancies for systemtap shell scripts +Requires: coreutils avahi avahi-utils mozilla-nss-tools zip unzip %description server SystemTap is an instrumentation system for systems running Linux 2.6. @@ -120,6 +127,7 @@ License: GPLv2+ Group: Development/Tools/Debuggers Summary: Static probe support tools Requires: %{name} = %{version}-%{release} +Requires: python %description sdt-devel SystemTap is an instrumentation system for systems running Linux 2.6. @@ -140,7 +148,7 @@ Authors: %else %setup -n %{name}-%{package_version} -q %endif -%patch -p1 +%patch1 -p1 %patch2 -p1 %patch3 -p1 %patch4 -p1 @@ -152,16 +160,19 @@ autoreconf -fi make %{?jobs:-j %jobs} %install -%if %suse_version < 1030 -# workaround for old autoconf -export MKDIR_P="mkdir -p" -%endif %makeinstall -mkdir -p $RPM_BUILD_ROOT/var/cache/systemtap -# doc subpackage is built separetely -# cp README AUTHORS NEWS COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ -rm -rf $RPM_BUILD_ROOT%{_docdir}/systemtap +# XXX +rm -f $RPM_BUILD_ROOT/usr/lib/systemtap/stap-server-request +# README, AUTHORS, NEWS, man3 and all examples packaged by systemtap-docs +# COPYING needs to stay in main for GPL +rm -rf $RPM_BUILD_ROOT%{_docdir}/systemtap/ rm -rf $RPM_BUILD_ROOT%{_mandir}/man3 +mkdir -p $RPM_BUILD_ROOT%{_docdir}/systemtap/ +cp COPYING $RPM_BUILD_ROOT%{_docdir}/systemtap/ +mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/cache/systemtap +mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/run/systemtap +mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/log +touch $RPM_BUILD_ROOT%{_localstatedir}/log/stap-server.log %clean rm -rf ${RPM_BUILD_ROOT} @@ -170,37 +181,51 @@ rm -rf ${RPM_BUILD_ROOT} %defattr(-,root,root) %{_bindir}/stap %{_mandir}/man1/* -%{_datadir}/systemtap -%dir %attr(0755,root,root) /var/cache/systemtap +%dir %{_datadir}/%{name} +%{_datadir}/%{name}/runtime +%{_datadir}/%{name}/tapset +#packaged by systemtap-initscript in upstream +%dir %{_localstatedir}/cache/systemtap +%dir %{_localstatedir}/run/systemtap %files runtime %defattr(-,root,root) +%doc %{_docdir}/systemtap %{_bindir}/staprun %{_bindir}/stap-report -%{_libexecdir}/systemtap -%{_mandir}/man8/staprun.* +%{_bindir}/stap-authorize-signing-cert +%dir %{_libexecdir}/%{name} +%{_libexecdir}/%{name}/stapio +%{_libexecdir}/%{name}/stap-env +%{_libexecdir}/%{name}/stap-authorize-cert +%{_mandir}/man8/staprun.8* +%{_mandir}/man8/stap-authorize-signing-cert.8* %files client %defattr(-,root,root) +%defattr(-,root,root) %{_bindir}/stap-client -%{_bindir}/stap-find-servers -%{_bindir}/stap-find-or-start-server -%{_bindir}/stap-start-server -%{_bindir}/stap-client-connect -%{_bindir}/stap-env +%{_bindir}/stap-authorize-server-cert +%{_libexecdir}/%{name}/stap-find-servers +%{_libexecdir}/%{name}/stap-client-connect +%{_mandir}/man8/stap-client.8* +%{_mandir}/man8/stap-authorize-server-cert.8* %files server %defattr(-,root,root) +%{_bindir}/stap-authorize-server-cert %{_bindir}/stap-server -%{_bindir}/stap-serverd -%{_bindir}/stap-start-server -%{_bindir}/stap-stop-server -%{_bindir}/stap-server-connect -%{_bindir}/stap-authorize* -%{_bindir}/stap-env -%{_bindir}/stap-gen-cert -%{_bindir}/stap-sign-module -%{_mandir}/man8/stap-server.* +%{_libexecdir}/%{name}/stap-serverd +%{_libexecdir}/%{name}/stap-start-server +%{_libexecdir}/%{name}/stap-find-servers +%{_libexecdir}/%{name}/stap-find-or-start-server +%{_libexecdir}/%{name}/stap-stop-server +%{_libexecdir}/%{name}/stap-gen-cert +%{_libexecdir}/%{name}/stap-server-connect +%{_libexecdir}/%{name}/stap-sign-module +%{_mandir}/man8/stap-server.8* +%{_mandir}/man8/stap-authorize-server-cert.8* +%ghost %{_localstatedir}/log/stap-server.log %files sdt-devel %defattr(-,root,root) From 2c4c28dfe33a41babe2463dcccd8c415fa71bb3a1035a268b770544b1eb13184 Mon Sep 17 00:00:00 2001 From: OBS User autobuild Date: Fri, 23 Jul 2010 19:25:50 +0000 Subject: [PATCH 7/8] Accepting request 43629 from devel:tools checked in (request 43629) OBS-URL: https://build.opensuse.org/request/show/43629 OBS-URL: https://build.opensuse.org/package/show/devel:tools/systemtap?expand=0&rev=13 --- systemtap.changes | 6 ------ systemtap.spec | 1 - 2 files changed, 7 deletions(-) diff --git a/systemtap.changes b/systemtap.changes index a93a6fd..e1bf13e 100644 --- a/systemtap.changes +++ b/systemtap.changes @@ -1,9 +1,3 @@ -------------------------------------------------------------------- -Wed Jul 21 12:51:32 CEST 2010 - vuntz@opensuse.org - -- Add python Requires to sdt-devel subpackage since dtrace is a - python script. - ------------------------------------------------------------------- Thu Mar 11 23:56:17 UTC 2010 - tonyj@novell.com diff --git a/systemtap.spec b/systemtap.spec index eb4a29b..ae93b08 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -127,7 +127,6 @@ License: GPLv2+ Group: Development/Tools/Debuggers Summary: Static probe support tools Requires: %{name} = %{version}-%{release} -Requires: python %description sdt-devel SystemTap is an instrumentation system for systems running Linux 2.6. From 34f4a4cddb5fa043d51f74359fe5e75f8a43387ee5f3d5f9872d0cab796d4ec8 Mon Sep 17 00:00:00 2001 From: OBS User buildservice-autocommit Date: Fri, 23 Jul 2010 19:25:51 +0000 Subject: [PATCH 8/8] Updating link to change in openSUSE:Factory/systemtap revision 54.0 OBS-URL: https://build.opensuse.org/package/show/devel:tools/systemtap?expand=0&rev=de0e33def1217bcb3e8e3124893d8868 --- systemtap-docs.spec | 2 +- systemtap.changes | 6 ++++++ systemtap.spec | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/systemtap-docs.spec b/systemtap-docs.spec index 61dd589..39be061 100644 --- a/systemtap-docs.spec +++ b/systemtap-docs.spec @@ -27,7 +27,7 @@ BuildRequires: latex2html %define use_snapshot 0 License: GPLv2+ Version: 1.1 -Release: 1 +Release: 2 Summary: Documents and examples for systemtap Group: Development/Tools/Debuggers Url: http://sourceware.org/systemtap/ diff --git a/systemtap.changes b/systemtap.changes index e1bf13e..a93a6fd 100644 --- a/systemtap.changes +++ b/systemtap.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed Jul 21 12:51:32 CEST 2010 - vuntz@opensuse.org + +- Add python Requires to sdt-devel subpackage since dtrace is a + python script. + ------------------------------------------------------------------- Thu Mar 11 23:56:17 UTC 2010 - tonyj@novell.com diff --git a/systemtap.spec b/systemtap.spec index ae93b08..ed1a7f2 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -24,7 +24,7 @@ BuildRequires: mozilla-nspr-devel mozilla-nss-devel mozilla-nss-tools %define use_snapshot 0 License: GPLv2+ Version: 1.1 -Release: 1 +Release: 2 Summary: Instrumentation System Group: Development/Tools/Debuggers Url: http://sourceware.org/systemtap/ @@ -127,6 +127,7 @@ License: GPLv2+ Group: Development/Tools/Debuggers Summary: Static probe support tools Requires: %{name} = %{version}-%{release} +Requires: python %description sdt-devel SystemTap is an instrumentation system for systems running Linux 2.6.