Bug 559719 (CVE-2010-0411)

Summary: CVE-2010-0411 systemtap: Crash with systemtap script using __get_argv()
Product: [Other] Security Response Reporter: Issue Tracker <tao>
Component: vulnerabilityAssignee: Red Hat Product Security <security-response-team>
Status: CLOSED ERRATA QA Contact:
Severity: medium Docs Contact:
Priority: medium    
Version: unspecifiedCC: bressers, djeffery, dsmith, fche, jistone, kreilly, mjw, tao, vdanen
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2012-09-10 21:15:06 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 561886, 561887, 561888, 561889, 561890    
Bug Blocks:    
Attachments:
Description Flags
Fix for __get_argv overflow
none
Rewrite __get_argv without embedded-C none

Description Issue Tracker 2010-01-28 20:09:27 UTC
Escalated to Bugzilla from IssueTracker

Comment 1 David Jeffery 2010-01-28 20:12:54 UTC
The length checking in the __get_argv() function in systemtap's tapset is faulty.  This failure can result in buffer overflows which will overwrite memory not controlled by systemtap.  The usual symptom is a crash from the slab do to a slab structure being overwritten.

Memory corruption can be triggered by anyone if a systemtap script using __get_argv() or the probe point syscall.execve is running.  A user just needs to start processes with very large argv lists.

The problem is caused by the improper handling of the return code from strlcpy().  The code in __get_argv():

                rc = strlcpy (str, buf, len);
                str += rc;
                len -= rc;

treats the return code as the amount of memory copied.  But it's not.  strlcpy() returns the equivalent of strlen(buf) which can be greater than len.  When copying multiple argv strings, this can result in len going negative.  And the len checks in __get_argv check for 0.  With len negative, __get_argv will continue copying the argv and overflow the memory buffer.


Steps to reproduce:

This is can be reproduced with a very minimal systemtap script. Run the systemtap script:

probe syscall.execve
{
       printf("%s\n", args);

}

The probe point syscall.execve uses __get_argv() internally to create the variable args.

Then, as any user run a loop executing a process with a really long arg list.  For example, "/bin/echo <ABSOLUTE_PATH_TO_KERNEL>/include/*/*" to get a huge arg list.  (Don't use the shell's built-in echo!) and occasionally dump /proc/slabinfo to force a walk of the slab structures.

#!/bin/bash
while [ "0" = "0" ] ; do
HOME=1
/bin/echo /usr/src/kernels/2.6.18-128.el5-PAE-i686/include/*/*

cat /proc/slabinfo
done

The test system would usually crash in under 30 seconds with the systemtap and shell script running.

Comment 2 Josh Stone 2010-01-28 22:10:37 UTC
I've confirmed the issue and filed it upstream:
http://sourceware.org/bugzilla/show_bug.cgi?id=11234

Comment 6 Frank Ch. Eigler 2010-01-29 01:31:23 UTC
A quick workaround/fix in the form of a patch to a file under /usr/share/systemtap/tapset is likely.

Comment 7 Josh Stone 2010-01-29 05:18:40 UTC
Created attachment 387497 [details]
Fix for __get_argv overflow

Here is a patch for /usr/share/systemtap/tapset/aux_syscall.stp, taken from upstream commit f754097.  I believe that __get_argv is sufficiently hardened with this fix, but let me know if you see anything else.

Thanks,
Josh

Comment 13 Vincent Danen 2010-02-04 15:57:34 UTC
This has been assigned CVE-2010-0411

Comment 21 Josh Stone 2010-02-05 02:49:27 UTC
Created attachment 388943 [details]
Rewrite __get_argv without embedded-C

We believe that this patch is preferable: the vulnerable functions are now written in the native script language, with all the protection that entails.

Comment 27 Fedora Update System 2010-02-15 18:07:24 UTC
systemtap-1.1-2.fc11 has been submitted as an update for Fedora 11.
http://admin.fedoraproject.org/updates/systemtap-1.1-2.fc11

Comment 28 Fedora Update System 2010-02-15 18:07:40 UTC
systemtap-1.1-2.fc12 has been submitted as an update for Fedora 12.
http://admin.fedoraproject.org/updates/systemtap-1.1-2.fc12

Comment 29 Fedora Update System 2010-02-18 22:23:13 UTC
systemtap-1.1-2.fc11 has been pushed to the Fedora 11 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 30 Fedora Update System 2010-02-18 22:36:23 UTC
systemtap-1.1-2.fc12 has been pushed to the Fedora 12 stable repository.  If problems still persist, please make note of it in this bug report.

Comment 31 errata-xmlrpc 2010-03-01 19:02:58 UTC
This issue has been addressed in following products:

  Red Hat Enterprise Linux 5

Via RHSA-2010:0124 https://rhn.redhat.com/errata/RHSA-2010-0124.html

Comment 32 errata-xmlrpc 2010-03-01 19:19:51 UTC
This issue has been addressed in following products:

  Red Hat Enterprise Linux 4

Via RHSA-2010:0125 https://rhn.redhat.com/errata/RHSA-2010-0125.html

Comment 35 David Smith 2010-03-09 15:19:09 UTC
(In reply to comment #34)
> Upstream patch:
> http://sourceware.org/git/gitweb.cgi?p=systemtap.git;a=patch;h=a2d399c87a642190f08ede63dc6fc434a5a8363a    

Actually, that patch, depending on the systemtap version, might or might not be the patch used to fix the problem.

Here's some history.  Originally, Josh fixed the embedded-C version of this function in this patch:

<http://sources.redhat.com/git/gitweb.cgi?p=systemtap.git;a=commitdiff;h=f75409719f120a3dbee66d761cf23a64092d1414>

Then, he decided to rewrite __get_argv without embedded-C.  That's the patch you referenced.

The "rewrite __get_argv without embedded-C" patch uses a systemtap feature that is only present in systemtap version 1.1 and up.  I'm referring to the "preprocessor conditional for kernel configuration testing" feature (which looks like "%( CONFIG_foo == "y" %? ... %)").

We decided to avoid backporting that new feature to older versions of systemtap.  So, versions of systemtap less than 1.1 have gotten the original fix (where Josh fixed the embedded-C version of __get_argv).  Systemtap versions of 1.1 or higher have gotten the "rewrite __get_argv without embedded-C" patch.