-
Notifications
You must be signed in to change notification settings - Fork 99
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
Question: unpack: reader size mismatch discarding trailing archive bits #358
Comments
I've not seen this before in the wild. How was the original image generated? If this error is not some other bug in umoci, it indicates that the descriptor pointing to a layer said it was 31101 bytes long but when the data was read it only contained 31100 bytes. If another tool was used to generate the images, that might be a bug in that other tool. This kind of error is similar to a hash mismatch, which is why it's a fatal error. (The reason the error comes up in the discard trailing archive bits code is because that's the last thing to read data from the verified reader -- the verified reader completes its verification on
They should see that all the files in
|
Thanks for the input! I'll try and collect some more information from the user with the issue, |
It is possible that the image is valid and it contains an extra byte at the end of the stream which umoci can't read (maybe someone added a NULL byte at the end of the GZIP stream?). If that is the issue we can work around it by reading any extra bytes after we've drained the gzip reader. |
Hi @cyphar - thanks for your input on this. Unfortunately the reporter hasn't provided any more information at this point. I'll ping them again. |
I just tried it and it looks like gzip ignores trailing bytes so we can safely discard them. I think this patch might solve the issue: diff --git a/oci/layer/unpack.go b/oci/layer/unpack.go
index 453b3a6a9b1f..6f129fcfa26b 100644
--- a/oci/layer/unpack.go
+++ b/oci/layer/unpack.go
@@ -273,9 +273,15 @@ func UnpackRootfs(ctx context.Context, engine cas.Engine, rootfsPath string, man
// in the later diff_id check failing because the digester didn't get
// the whole uncompressed stream). Just blindly consume anything left
// in the layer.
- if _, err = io.Copy(ioutil.Discard, layer); err != nil {
+ if _, err := io.Copy(ioutil.Discard, layer); err != nil {
return errors.Wrap(err, "discard trailing archive bits")
}
+ // Same goes for compressed layers -- it seems like some gzip
+ // implementations add trailing NUL bytes, which Go doesn't slurp up.
+ // Just eat up the rest of the remaining bytes and discard them.
+ if _, err := io.Copy(ioutil.Discard, layerRaw); err != nil {
+ return errors.Wrap(err, "discard trailing raw bits")
+ }
if err := layerData.Close(); err != nil {
return errors.Wrap(err, "close layer data")
}
diff --git a/pkg/hardening/verified_reader.go b/pkg/hardening/verified_reader.go
index 0063aea328f2..20b03dd6e983 100644
--- a/pkg/hardening/verified_reader.go
+++ b/pkg/hardening/verified_reader.go
@@ -160,6 +160,12 @@ func (v *VerifiedReadCloser) Read(p []byte) (n int, err error) {
// Close is a wrapper around VerifiedReadCloser.Reader, but with a digest check
// which will return an error if the underlying Close() didn't.
func (v *VerifiedReadCloser) Close() error {
+ // Consume any remaining bytes to make sure that we've actually read to the
+ // end of the stream. VerifiedReadCloser.Read will not read past
+ // ExpectedSize+1, so we don't need to add a limit here.
+ if _, err := io.Copy(ioutil.Discard, v); err != nil {
+ return errors.Wrap(err, "consume remaining unverified stream")
+ }
// Piped to underlying close.
err := v.Reader.Close()
if err != nil { |
I might also want to add some kind of debugging information to indicate that there were trailing bytes, since this indicates a bug in the image generator being used. |
I think #360 should fix this issue. |
Thank you for your work on this. I'll try to get the affected user on our side to try it out with their image. |
Ah it turns out that patch is broken because of a bug in https://github.com/klauspost/pgzip. I will try to rustle up a slightly different patch we can merge today while we wait for #360 to be mergeable. |
@dtrudg I will release a new version of umoci tomorrow -- is it possible to get the user to try with the updated version at some point? |
Thanks @cyphar - the user hasn't responded to my previous question, unfortunately, but I'll create a PR today on our end with the current umoci master and ask if they can test. Thanks again. |
@cyphar - many thanks again for this. We released with umoci 0.4.7 today, so we should find out in due course if it's a fix. Apologies I haven't been able to get confirmation from the user. |
No worries, let me know if you get any response. :D |
This is a question rather than an issue report, as I cannot reproduce with any other image, and our reporter cannot provide the image they have which causes this behavior. Please feel free to close for lack of information!
We have had a report of an umoci unpack failing on an image (which unfortunately the reporter cannot provide).
apptainer/singularity#5799
Umoci reports:
Looking at the code, umoci is discarding padding etc. here as expected but I'm not clear why the stream could end up 1 byte shorter than expected.
Just wondering whether this has ever been seen before?
The text was updated successfully, but these errors were encountered: