Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpmsign --delsign leaves behind 0 padding #2965

Open
JanZerebecki opened this issue Mar 12, 2024 · 7 comments
Open

rpmsign --delsign leaves behind 0 padding #2965

JanZerebecki opened this issue Mar 12, 2024 · 7 comments
Milestone

Comments

@JanZerebecki
Copy link
Contributor

Describe the bug
rpmsign --delsign leaves behind 0 padding, previously similar problem in #2382 fixed by #2396

To Reproduce
Steps to reproduce the behavior:

  1. rebuild locally: osc co openSUSE:Factory scout && cd openSUSE:Factory/scout/ && osc build --clean -x '' --release 2.1 --build-opt=--disturl=obs://build.opensuse.org/openSUSE:Factory/standard/d2d01ca7d9d5f8c1de2fe35a07f4c223-scout --no-service
  2. get remote build result: osc getbinaries openSUSE:Factory scout standard x86_64
  3. rpmsign --delsign 2.rpm
  4. diffoscope 1.rpm 2.rpm
  5. should be no difference, but it seems there is additional 0 padding in rpms from step 2
  6. @bmwiedemann tested the same also with Fedora its rpm and rpmsign
  7. cp 1.rpm 3.rpm
  8. rpmsign --addsign 3.rpm
  9. rpmsign --delsign 3.rpm
  10. content of 1.rpm and 3.rpm is the same

tar.gz of 1.rpm and 2.rpm and the one the remote one before deleting the signature

Expected behavior
rpmsign --delsign does not add different amount of 0 padding

Environment

  • OS / Distribution: Fedora, openSUSE Factory, Tumbleweed
  • Version rpm 4.19.1.1

Additional context
@bmwiedemann reported this for openSUSE Factory, which is now supposed to be bit reproducible except signature: https://old.reddit.com/r/reproduciblebuilds/comments/1bcz7r2/got_closer_to_reproducible_rpm_builds/

@pmatilai
Copy link
Member

rpmsign cannot know what the previous reservation (if any) was, so it cannot guarantee going back to the former state on --delsign.

That said, there's something very wonky here, the reserved space doesn't appear to get used at all on signing, although it does reclaim the space from the --delsig. Thanks for reporting!

@JanZerebecki
Copy link
Contributor Author

Bernhard mentioned that the size of the rpm stays the same on --delsign, but should shrink by 1104 bytes. I haven't calculated it myself but the direction of that looks right and a quick read of the code looks like it should be doing that (but I would need look much more careful to identify why it doesn't here).

So it looks to me like it is not reclaiming the space during --delsign. Where or why do we disagree?

It looks to me like the reservation is hard coded. So as long as the rpm that was used to build and the one that was used to --delsign is the same it should be able to guarantee it, right?

When adding a signature locally output size remains the same as the input, with rpm-4.19.1.1-3.1.x86_64 from Tumbleweed, same result with input binary from step 1 and 2.

I think the signing code that produced 2 is from https://github.com/openSUSE/obs-sign , so that might be creating a binary that this projects code can not deal with. And that project also changed. Though with some older version of both projects this worked.

Even if an rpm has too much padding, the intent of the code for --delsign seems to me to fix that by further decreasing the size to what it has hard coded, but fails here.

@pmatilai
Copy link
Member

So it looks to me like it is not reclaiming the space during --delsign. Where or why do we disagree?

It looks to me like the reservation is hard coded. So as long as the rpm that was used to build and the one that was used to --delsign is the same it should be able to guarantee it, right?

Except for a bare minimum, the reservation is macro configurable, so it can be anything at all. And that's why it cannot possibly guarantee to restore it. In an arbitrary situation that is.

When the signature fits in the original reservation then it should restore it to original condition though. So like I said, there's something very wonky here. As in, it's a bug or more likely, regression.

@bmwiedemann
Copy link
Contributor

After 2022-06-20 we changed to a new rsa4096 signkey for the project.
%__gpg_reserved_space seems to default to 4096 bytes so that should fit. And indeed, rpm --delsign leaves the size as is.

With this dump-rpm-headers.py I get this diff between our delsigned OBS build and my local build:

--- dump-rpm-headers.py binaries/strip-nondeterminism-1.13.1-33.11.src.rpm
+++ dump-rpm-headers.py binaries.nachbau/strip-nondeterminism-1.13.1-33.11.src.rpm
@@ -13,15 +13,15 @@
    version: b'\x01'
   reserved: b''
     nindex: 7
-     hsize: 4868
+     hsize: 4276
 ==== Signature Section - Index Entries ====
-[  0] tag:   62  type: BIN          offset:4852  count:  16   # RPMTAG_HEADERSIGNATURES
+[  0] tag:   62  type: BIN          offset:4260  count:  16   # RPMTAG_HEADERSIGNATURES
 [  1] tag:  269  type: STRING       offset:   0  count:   1   # RPMSIGTAG_SHA1
 [  2] tag:  273  type: STRING       offset:  41  count:   1   # Unknown
 [  3] tag: 1000  type: INT32        offset: 108  count:   1   # RPMSIGTAG_SIZE
 [  4] tag: 1004  type: BIN          offset: 112  count:  16   # RPMSIGTAG_MD5
 [  5] tag: 1007  type: INT32        offset: 128  count:   1   # RPMSIGTAG_PAYLOADSIZE
-[  6] tag: 1008  type: BIN          offset: 132  count:4720   # RPMSIGTAG_RESERVEDSPACE
+[  6] tag: 1008  type: BIN          offset: 132  count:4128   # RPMSIGTAG_RESERVEDSPACE
 ==== Signature Section - Data ====
 [  1] RPMSIGTAG_SHA1
 b'34a3e2de398c3a6598b6b4b9d01d9a7fa96fda48'
@@ -42,43 +42,6 @@ RPMSIGTAG_RESERVEDSPACE
 0000 0000 0000 0000 0000 0000 0000 0000 
 0000 0000 0000 0000 0000 0000 0000 0000 
 0000 0000 0000 0000 0000 0000 0000 0000 
-0000*

So there is a difference of 592 bytes, which is around the size of a 4096-bit sig.

@pmatilai
Copy link
Member

Just FWIW, there's now an in-tree tool for looking at low-level package structure:
https://github.com/rpm-software-management/rpm/blob/master/tools/rpmdump.c

@JanZerebecki
Copy link
Contributor Author

Had a very old version of rpm around and this worked, I can confirm it is a regression in rpm.

@bmwiedemann
Copy link
Contributor

I think, the problem has 2 components.

  1. The obs-sign we use in OBS has its own signing code and adds bytes to the header instead of using the reserved space.
  2. The rpm --delsign leaves the (increased) size as is, only zeroes it out.

I was able to get bit-identical results to OBS using "--define=%__gpg_reserved_space 4688" in the replication build to add as many header bytes as obs-sign did, but that is certainly not the nicest solution.

bmwiedemann added a commit to bmwiedemann/reproducibleopensuse that referenced this issue Mar 26, 2024
@pmatilai pmatilai added this to the 4.20.0 milestone Apr 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Priority
Development

No branches or pull requests

3 participants