-
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
image-rs: Handle gzip whiteouts correctly #687
Conversation
image-rs/src/unpack.rs
Outdated
@@ -60,6 +130,10 @@ pub async fn unpack<R: AsyncRead + Unpin>(input: R, destination: &Path) -> Resul | |||
.try_into() | |||
.context("GID is too large!")?; | |||
|
|||
if !convert_whiteout(&file.path()?, file.header(), destination)? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that there are some duplicated logic between convert_whiteout
and unpack
after line 139. Could we do some refactoring upon this commit to avoid this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I will refactor it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Xynnn007 I pushed some changes. Is that what you have in mind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the refactoring! Two last comments and other parts looks perfect to me
image-rs/src/unpack.rs
Outdated
} | ||
|
||
#[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "macos"))] | ||
use anyhow::anyhow; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's move this
use anyhow::anyhow;
directly inside convert_whiteout
image-rs/src/unpack.rs
Outdated
|
||
#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "macos")))] | ||
fn convert_whiteout(path: &Path, uid: u32, gid: u32, mode: Option<u32>, destination: &Path) -> Result<bool> { | ||
Ok(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably we could use a shared convert_whiteout
funciton. With cfg-if
to firstly judge the platform and return Ok(true)
if needed. Thus we do not need two convert_whiteout
versions.
FWIW, I've built images with whiteouts using the distroless tooling in the past. In case it's useful.. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last thing. Sorry I did not make it clear
image-rs/src/unpack.rs
Outdated
mode: Option<u32>, | ||
destination: &Path, | ||
) -> Result<bool> { | ||
if cfg!(target_os = "linux") || cfg!(target_os = "freebsd") || cfg!(target_os = "macos") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can try to return ASAP to avoid big {..}
block
if !cfg!(target_os = "linux") && !cfg!(target_os = "freebsd") && !cfg!(target_os = "macos") {
return Ok(true)
}
... other logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good. A rebase is needed
0aa479f
to
0c2c5b6
Compare
image-rs/src/unpack.rs
Outdated
bail!("mknod: {:?} error: {:?}", path, io::Error::last_os_error()); | ||
} | ||
|
||
set_perms_ownerships(&path, ChownType::LChown, uid, gid, mode).await?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need also to set_file_times()
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good question. Looking into the golang base implementation, set_file_times
is not done.
The purpose of the whiteout file is to hide the original file. Even if we update the file times, it is not going to be visible in the file system.
2ad2ced
to
f65dd6d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. A few comments. I guess this is mainly being ported from the Go code, but I'd like to understand a little better what's happening.
image-rs/src/unpack.rs
Outdated
@@ -77,6 +129,11 @@ pub async fn unpack<R: AsyncRead + Unpin>(input: R, destination: &Path) -> Resul | |||
.gid()? | |||
.try_into() | |||
.context("GID is too large!")?; | |||
let mode = file.header().mode().ok(); | |||
|
|||
if unpack_xattrs && !convert_whiteout(&file.path()?, uid, gid, mode, destination).await? { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess you might have inherited some of this code, but the logic here seems a bit odd to me. convert_whiteout
doesn't necessarily convert a whiteout. It checks if we are pointing to a whiteout file and then converts it if needed. This results in a slightly clunky Result<bool>
being returned.
What about making two functions. One called is_whiteout
which returns Result<bool>
and one called convert_whiteout
which just returns a Result<()>
This seem like a bit of messing around but I think it will make this nicer.
image-rs/src/unpack.rs
Outdated
original_path.display() | ||
))?; | ||
|
||
let ret = unsafe { nix::libc::mknod(path.as_ptr(), nix::libc::S_IFCHR, 0) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused by this part. Is this a trick to get rid of a file from a lower layer at the same location as the whiteout? It might be good to put a comment here (and maybe also a higher-level one with some reference to a spec) since this is a somewhat unusual operation. Why not just delete the file at that path or am I totally off here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This mknod
thing is still a bit mysterious to me, but I guess we can live with it.
Fixes: confidential-containers#604 Signed-off-by: Silenio Quarti <[email protected]>
|
image-rs/src/unpack.rs
Outdated
original_path.display() | ||
))?; | ||
|
||
let ret = unsafe { nix::libc::mknod(path.as_ptr(), nix::libc::S_IFCHR, 0) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure we use nix
here, s.t. https://docs.rs/nix/0.29.0/nix/sys/stat/fn.mknod.html If we can, we will get code w/o unsafe
parts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure this is what you are after.
Signed-off-by: Silenio Quarti <[email protected]>
Thanks @squarti Let's keep an eye on image unpacking when we next bump guest-components just in case. |
This PR readds whiteout handling on platforms that support xattr
Fixes: #604