Bug 1224555

Summary: regression in rpm 4.12 : cpio bad magic
Product: [Fedora] Fedora Reporter: Casey Harkins <charkins>
Component: rpmAssignee: Packaging Maintenance Team <packaging-team-maint>
Status: CLOSED NOTABUG QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: unspecified Docs Contact:
Priority: unspecified    
Version: 21CC: charkins, jzeleny, lkardos, novyjindrich, packaging-team-maint, pknirsch
Target Milestone: ---   
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2015-05-26 07:19:38 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
rpm file which triggers error
none
verbose log from rpm during install attempt
none
gradle build file used to generate rpm w/ redline via os-package plugin none

Description Casey Harkins 2015-05-24 16:07:31 UTC
Created attachment 1029223 [details]
rpm file which triggers error

Description of problem:

There appears to be a regression in rpm 4.12.0.1 which causes a "error: unpacking of archive failed: cpio: Bad magic" error with an rpm created by redline with a symlink. It is possible this is actually a bug in redline's construction of the rpm which is only triggered on rpm 4.12.0.1. The error is not triggered on rpm 4.8.0 on CentOS or 4.11.3 on Fedora 20.

Version-Release number of selected component (if applicable):

  rpm-4.12.0.1-6.fc21.x86_64

How reproducible:

  100% reproducible with attached rpm.

Steps to Reproduce:
  1. rpm -iv foo-1.0.0-1.noarch.rpm

Actual results: (Fedora 21 w/ rpm-4.12.0.1-6.fc21.x86_64)

  Preparing packages...
  foo-0:1.0.0-1.noarch
  error: unpacking of archive failed: cpio: Bad magic
  error: foo-0:1.0.0-1.noarch: install failed

Untracked files left in /opt/foo.


Expected results: (Fedora 20 w/ rpm-4.11.3-1.fc20.x86_64)

  Preparing packages...
  foo-0:1.0.0-1.noarch

Also tested successfully on CentOS 6 w/  rpm 4.8.0.

Additional info:

The rpm is attached. It was generated with a minimal gradle script using the nebula.os-package gradle plugin (build.gradle attached). It can be recreated by running 'gradle fooRpm' in a directory containing build.gradle.

Commenting out the 'link' line in build.gradle will create an rpm without the symlink. The resulting rpm can be successfully installed on Fedora 21, so the problem seems to be specific to the symlink.

Comment 1 Casey Harkins 2015-05-24 16:08:35 UTC
Created attachment 1029224 [details]
verbose log from rpm during install attempt

Comment 2 Casey Harkins 2015-05-24 16:09:33 UTC
Created attachment 1029225 [details]
gradle build file used to generate rpm w/ redline via os-package plugin

Comment 3 Casey Harkins 2015-05-24 21:12:40 UTC
The relevant code in lib/cpio.c triggering the error:

    #define CPIO_NEWC_MAGIC "070701"
    #define CPIO_CRC_MAGIC  "070702"

    ...


    if (strncmp(CPIO_CRC_MAGIC, magic, sizeof(CPIO_CRC_MAGIC)-1) &&
        strncmp(CPIO_NEWC_MAGIC, magic, sizeof(CPIO_NEWC_MAGIC)-1)) {

            return RPMERR_BAD_MAGIC;
    }


When trying to install the attached rpm, magic is "/opt/f" at the point of failure. I don't know enough about the rpm file format (yet) to figure out if the problem is with the rpm itself but somehow earlier rpm versions are more forgiving, or if it is an obscure bug here in rpm 4.12.0.1.

I suspect the behavior changed in rpm with this commit, but haven't confirmed:

https://github.com/rpm-software-management/rpm/commit/000dc5f499b34de55026c3ba33dc83de669d5b96

Comment 4 Casey Harkins 2015-05-25 03:17:17 UTC
The first two entries in the cpio are getting handled correctly (directory /opt/foo and regular file /opt/foo/build.gradle). The third entry is the symlink. The cpio header is getting read correctly by rpm, including reading the file size as 21 bytes. However, the file size from the cpio header is not being used in lib/rpmfi.c iterReadArchiveNext():

   } else if (S_ISLNK(mode)) {
        /* Skip over symlink target data in payload */
        rpm_loff_t lsize = rpmfilesFSize(fi->files, fx);

It appears to be getting the size from elsewhere in the rpm. In this case it is returning a size of 0 for this symlink instead of 21. Is there an easy way to dump the full file info from the rpm?

Obviously the zero size is the problem. rpm does not read or skip the symlink data before trying to read the header for the next cpio entry (the TRAILER!!!). Instead of getting the magic number, its getting the first 6 bytes of the symlink data ("/opt/f").

Comment 5 Ľuboš Kardoš 2015-05-25 14:11:37 UTC
Your rpm package wasn't created correctly. The size of file /opt/foo/linked.gradle is not set properly in rpm header:

$ rpm -qp --qf "[%{filenames} %{filesizes}\n]" /tmp/foo-1.0.0-1.noarch.rpm
/opt/foo 4096
/opt/foo/build.gradle 349
/opt/foo/linked.gradle 0

How does redline construct rpm? Does it use rpmbuild somehow? 

To dump whole rpm header you can use "rpm -q --xml -p /tmp/foo-1.0.0-1.noarch.rpm".

Comment 6 Casey Harkins 2015-05-25 17:41:15 UTC
I had just discovered that the filesize for the symlink was 0 in the rpm header entry, though I walked my way through the rpm with a hex editor. I knew there had to be an easier way to dump out the header (or query the header fields). Thanks for the help there!

redline is a pure java library, so it does not rely upon rpmbuild for constructing the rpm. This is obviously a bug in redline not setting the size properly for the symlink (I'll file a bug with them and possible a patch).

It is interesting that older versions of rpm work fine. I suspect that they were relying upon the filesize from the cpio header rather than the rpm header.

Thanks again for your help! This can be closed as not a bug. (I'm not clearing the needinfo if that helps).