This service will be undergoing maintenance at 20:00 UTC, 2017-04-03. It is expected to last about 30 minutes
Bug 1273360 - rpm: crash when parsing corrupted RPM file
rpm: crash when parsing corrupted RPM file
Status: CLOSED WONTFIX
Product: Security Response
Classification: Other
Component: vulnerability (Show other bugs)
unspecified
All Linux
low Severity low
: ---
: ---
Assigned To: Red Hat Product Security
impact=low,public=20151106,reported=2...
: Security
Depends On: 1278797
Blocks: 1270711
  Show dependency treegraph
 
Reported: 2015-10-20 05:38 EDT by Stefan Cornelius
Modified: 2016-10-28 04:27 EDT (History)
5 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2016-10-28 04:27:51 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)

  None (edit)
Description Stefan Cornelius 2015-10-20 05:38:29 EDT
t was discovered that rpm did not properly parse certain corrupt RPM files. This can be exploited to cause a crash by tricking an unsuspecting user into processing a specially crafted RPM file.
Comment 2 Stefan Cornelius 2015-10-20 10:46:20 EDT
I think the problem is within the "CompressFilelist()" function in lib/legacy.c.

It allocates memory to store filename data from the header:
50 baseNames = xmalloc(sizeof(*dirNames) * count);

It then attempts to do some processing in order to fill this memory with sane data:
 72     while ((i = rpmtdNext(&fileNames)) >= 0) {
 73     char ** needle;
 74     char savechar;
 75     char * baseName;
 76     size_t len;
 77     char *filename = (char *) rpmtdGetString(&fileNames); /* HACK HACK */
 78
 79     if (filename == NULL)    /* XXX can't happen */
 80         continue;
 81     baseName = strrchr(filename, '/') + 1;
 82     len = baseName - filename;
 83     needle = dirNames;
 84     savechar = *baseName;
 85     *baseName = '\0';
 86     if (dirIndex < 0 ||
 87         (needle = bsearch(&filename, dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
 88         char *s = xmalloc(len + 1);
 89         rstrlcpy(s, filename, len + 1);
 90         dirIndexes[i] = ++dirIndex;
 91         dirNames[dirIndex] = s;
 92     } else
 93         dirIndexes[i] = needle - dirNames;
 94
 95     *baseName = savechar;
 96     baseNames[i] = baseName;
 97     }
 98
 99 exit:
100     if (count > 0) {
101     headerPutUint32(h, RPMTAG_DIRINDEXES, dirIndexes, count);
102     headerPutStringArray(h, RPMTAG_BASENAMES, baseNames, count);
103     headerPutStringArray(h, RPMTAG_DIRNAMES,
104                  (const char **) dirNames, dirIndex + 1);

In case of the rpm provided, the (filename == NULL) check in line 79 will be true in every iteration, thus the remaining processing steps in this loop are always skipped and "baseNames" is never put in a state that's expected by subsequent functions, which are called via headerPutStringArray() in line 102. This will ultimately lead to a crash due to invalid memory access in a strlen() function.
Comment 7 Stefan Cornelius 2015-11-06 07:53:09 EST
Created rpm tracking bugs for this issue:

Affects: fedora-all [bug 1278797]
Comment 8 Fedora Update System 2015-11-23 15:53:27 EST
rpm-4.13.0-0.rc1.7.fc23 has been pushed to the Fedora 23 stable repository. If problems still persist, please make note of it in this bug report.
Comment 9 Fedora Update System 2015-11-30 18:22:23 EST
rpm-4.12.0.1-14.fc22 has been pushed to the Fedora 22 stable repository. If problems still persist, please make note of it in this bug report.

Note You need to log in before you can comment on or make changes to this bug.