Bug 1224555 - regression in rpm 4.12 : cpio bad magic
Summary: regression in rpm 4.12 : cpio bad magic
Keywords:
Status: CLOSED NOTABUG
Alias: None
Product: Fedora
Classification: Fedora
Component: rpm
Version: 21
Hardware: x86_64
OS: Linux
unspecified
unspecified
Target Milestone: ---
Assignee: Packaging Maintenance Team
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2015-05-24 16:07 UTC by Casey Harkins
Modified: 2015-05-26 07:19 UTC (History)
6 users (show)

Fixed In Version:
Clone Of:
Environment:
Last Closed: 2015-05-26 07:19:38 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)
rpm file which triggers error (2.52 KB, application/x-rpm)
2015-05-24 16:07 UTC, Casey Harkins
no flags Details
verbose log from rpm during install attempt (6.39 KB, text/plain)
2015-05-24 16:08 UTC, Casey Harkins
no flags Details
gradle build file used to generate rpm w/ redline via os-package plugin (349 bytes, text/plain)
2015-05-24 16:09 UTC, Casey Harkins
no flags Details

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).


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