Bug 1213277

Summary: rpm crashes when passed invalid file
Product: [openSUSE] openSUSE Tumbleweed Reporter: Jiri Slaby <jslaby>
Component: BasesystemAssignee: Michael Schröder <mls>
Status: RESOLVED WONTFIX QA Contact: E-mail List <qa-bugs>
Severity: Normal    
Priority: P5 - None CC: jengelh
Version: Current   
Target Milestone: ---   
Hardware: Other   
OS: Other   
Whiteboard:
Found By: --- Services Priority:
Business Priority: Blocker: ---
Marketing QA Status: --- IT Deployment: ---
Attachments: _buildenv

Description Jiri Slaby 2023-07-13 07:46:52 UTC
Created attachment 868175 [details]
_buildenv

Run rpm with the attached file:
# rpm -Fvh _buildenv
Program received signal SIGSEGV, Segmentation fault.

I did
rpm -Fvh *

in a directory created by "osc getbinaries". I know I should've used *.rpm, but rpm should not crash when passed bad files.

It looks like it recurses in glob() to death:
> #0  0x00007ffff7f0d934 in glob (
>     pattern=pattern@entry=0x7fffff81ce80 "didnt move in 1.5h (seen in libreoffice builds) BuildFlags: logidlelimit:5400 %endif %if &quot;%_project&quot; == &quot;openSUSE:Factory&quot; || &quot;%_project&quot; == &quot;openSUSE:Factory:NonFre"..., flags=flags@entry=5152, pglob=pglob@entry=0x7fffffffb5d0, errfunc=0x0)
>     at /usr/src/debug/rpm-4.18.0/rpmio/rpmglob.c:165
> #1  0x00007ffff7f0e2fc in glob (
>     pattern=pattern@entry=0x7fffff83f090 "didnt move in 1.5h (seen in libreoffice builds) BuildFlags: logidlelimit:5400 %endif %if &quot;%_project&quot; == &quot;openSUSE:Factory&quot; || &quot;%_project&quot; == &quot;openSUSE:Factory:NonFre"..., flags=flags@entry=5152, pglob=pglob@entry=0x7fffffffb5d0, errfunc=0x0)
>     at /usr/src/debug/rpm-4.18.0/rpmio/rpmglob.c:213
> #2  0x00007ffff7f0e2fc in glob (
>     pattern=pattern@entry=0x7fffff8612a0 "didnt move in 1.5h (seen in libreoffice builds) BuildFlags: logidlelimit:5400 %endif %if &quot;%_project&quot; == &quot;openSUSE:Factory&quot; || &quot;%_project&quot; == &quot;openSUSE:Factory:NonFre"..., flags=flags@entry=5152, pglob=pglob@entry=0x7fffffffb5d0, errfunc=0x0)
>     at /usr/src/debug/rpm-4.18.0/rpmio/rpmglob.c:213
> ...
> #58 0x00007ffff7f0e2fc in glob (
>     pattern=pattern@entry=0x7ffffffd92d0 "didnt move in 1.5h (seen in libreoffice builds) BuildFlags: logidlelimit:5400 %endif %if &quot;%_project&quot; == &quot;openSUSE:Factory&quot; || &quot;%_project&quot; == &quot;openSUSE:Factory:NonFre"..., flags=flags@entry=5152, pglob=pglob@entry=0x7fffffffb5d0, errfunc=0x0)
>     at /usr/src/debug/rpm-4.18.0/rpmio/rpmglob.c:213
> #59 0x00007ffff7f0e2fc in glob (
>     pattern=0x7ffff7596fc4 "didnt move in 1.5h (seen in libreoffice builds) BuildFlags: logidlelimit:5400 %endif %if &quot;%_project&quot; == &quot;openSUSE:Factory&quot; || &quot;%_project&quot; == &quot;openSUSE:Factory:NonFre"...,
>     flags=flags@entry=5120, pglob=pglob@entry=0x7fffffffb5d0, errfunc=0x0)
>     at /usr/src/debug/rpm-4.18.0/rpmio/rpmglob.c:213
> #60 0x00007ffff7f0f073 in rpmGlob (
>     patterns=patterns@entry=0x7ffff75dd010 "<buildinfo project=\"graphics:gimp:master\" repository=\"openSUSE_Tumbleweed\" package=\"maxflow\"> <arch>x86_64</arch> <srcmd5>59b2ebc06df29ffc1e28e301625e9be2</srcmd5> <verifymd5>59b2ebc06df29ffc1e28e3016"..., argcPtr=argcPtr@entry=0x7fffffffb73c,
>     argvPtr=argvPtr@entry=0x7fffffffb740)
>     at /usr/src/debug/rpm-4.18.0/rpmio/rpmglob.c:864
> #61 0x00007ffff7f4b45a in rpmReadPackageManifest (fd=<optimized out>,
>     argcPtr=0x5555555728e8, argvPtr=0x5555555728f0)
>     at /usr/src/debug/rpm-4.18.0/lib/manifest.c:121
> #62 0x00007ffff7f667b3 in tryReadManifest (eiu=0x5555555728b0)
>     at /usr/src/debug/rpm-4.18.0/lib/rpminstall.c:333
> #63 rpmInstall (ts=ts@entry=0x555555571b30, ia=<optimized out>,
>     fileArgv=<optimized out>) at /usr/src/debug/rpm-4.18.0/lib/rpminstall.c:565
> #64 0x00005555555567e1 in main (argc=3, argv=<optimized out>)
>     at /usr/src/debug/rpm-4.18.0/rpm.c:274
Comment 1 Michael Schröder 2023-07-13 12:40:26 UTC
The manifest reading code in rpm-4.18 is a bit... peculiar. It works by joining all the lines into one string and then splitting them again via a call to popt.
Popt knows about quoting, so the single quote of the "didn't" is matched against the next single quote resulting in a quite long string.

This string is then fed into rpm's internal glob implementation, which is a very outdated copy from the glibc implementation. This code then tries to expand any {} constructs, leading the quite a bit of recursion. Plus, the patterns are using stack space via "char onealt[strlen(pattern) - 1];". So it's not surprising that this runs into the stack limit.

All this already has been fixed in rpm-upstream, so the upcoming rpm update for Fectory will no longer run into this. And as this is not a security problem I will not try to backport the (quite big) changeset.