-
Notifications
You must be signed in to change notification settings - Fork 797
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
buildah build
: use the same overlay for the context directory for the whole build
#5975
base: main
Are you sure you want to change the base?
Conversation
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: nalind The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
51a061b
to
9d7189f
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.
Thanks so much for working on this! I just skimmed the code, will try testing it soon
@@ -63,6 +63,13 @@ func MountWithOptions(contentDir, source, dest string, opts *Options) (mount spe | |||
if err := os.Chown(upperDir, int(stat.Uid), int(stat.Gid)); err != nil { | |||
return mount, err | |||
} | |||
times := []syscall.Timeval{ |
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.
Why out of curiosity? Is this helping ensure reproducibility? We aren't serializing anything related to the timestamps of this directory to e.g. a tar stream are we?
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.
Without it, two different runs would appear to have different timestamps on the top level of the build context directory, breaking one of the tests added by #5691.
// indicates whether we did, in fact, mount an overlay; a cleanup function | ||
// which should be called when the location is no longer needed (on success); | ||
// and a non-nil fatal error if any of that failed. | ||
func platformSetupContextDirectoryOverlay(store storage.Store, options *define.BuildOptions) (string, string, string, bool, func(), error) { |
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.
Return values are a bit unwieldy, maybe a struct
instead? Although I guess the single caller unpacks them anyways, so doesn't matter. Yeah, one caller, so makes sense as is.
pkg/cli/build.go
Outdated
@@ -113,7 +113,7 @@ func GenBuildOptions(c *cobra.Command, inputArgs []string, iopts BuildOptions) ( | |||
if c.Flag("build-context").Changed { | |||
for _, contextString := range iopts.BuildContext { | |||
av := strings.SplitN(contextString, "=", 2) | |||
if len(av) > 1 { | |||
if len(av) > 1 && av[0] != "" && av[1] != "" { |
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 is basically so we skip over -v :
or something? This could use a comment, maybe even we have a const DefaultBuildContextKey = ""
and then reference it 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.
Pushing the check on av[1]
down into GetAdditionalBuildContext()
makes it a little easier to follow, added a comment here and put more checks in there.
@@ -673,7 +673,7 @@ symlink(subdir)" | |||
_prefetch busybox | |||
run_buildah 125 build -t testbud3 $WITH_POLICY_JSON $BUDFILES/dockerignore3 | |||
expect_output --substring 'building.*"COPY test1.txt /upload/test1.txt".*no such file or directory' | |||
expect_output --substring $(realpath "$BUDFILES/dockerignore3/.dockerignore") | |||
expect_output --substring 'filtered out using /[^ ]*/.dockerignore' |
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.
It's not obvious to me how this test change is related...did the build there try to modify the context directory?
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.
The name of the directory which contains the .dockerignore file and which is included in the error message is no longer the one passed on the command line, so the exact string comparison began failing. It was either change the test to not care about the specific path, or lie about the file's location to get the test to pass as it was, so I changed the test.
1e2d39c
to
82ee991
Compare
imagebuildah/stage_executor.go
Outdated
@@ -916,6 +929,58 @@ func (s *StageExecutor) UnrecognizedInstruction(step *imagebuilder.Step) error { | |||
return errors.New(err) | |||
} | |||
|
|||
// do our best to ensure that image specifiers that include a transport that | |||
// uses path names are scoped to the build context directory |
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.
It'd be secure and reliable to get a directory fd for the context overlay mount, and then use openat(..., RESOLVE_IN_ROOT)
to access the file, then...the ugly part is that the containers-storage APIs want path strings still, but we could pass e.g. oci:/proc/self/fd/N
right? I've done that elsewhere I think.
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.
Proper safety for such references is a much larger patch.
Trying to test this, but unrelated to the contents of this PR, I get the same problem trying git main:
Is there something I need to do here to sync up the buildah binary with the default network config? Odd... |
Nevermind of course after I posted my "wait these are weird denials" mental flag tripped and of course it's SELinux; a |
OK so this works for me:
So that's already a lot cleaner, thanks! There is an important note here that this does break compatibility with the previous dockerfiles, I get:
Looks like changing Now that I dig in a bit more, one unfortunate thing here is that the need to use the When I unpack and inspect the resulting image, we have this final layer with
with floating timestamps. That said hmm, actually in this case actually it works to do But the sad thing is that these things just keep piling on...now for me we have a new one of these in Konflux which is injecting content_sets which also has no attempt made to generate timestamp-reproducible data right now either (and it uses buildah too, so it inherits that, but we still need to ensure the timestamps of the files that we actually write and aren't synthetic container runtime artifacts are canonicalized too) So in the end, I think we'll definitely try to |
Not being strict about the arguments for |
63f0cda
to
5b05378
Compare
In addition to setting the (usually recently-created) upper directory's ownership and permissions to match those of the lower (the location of which wasn't known when the upper was created), set the timestamps to match, too. Signed-off-by: Nalin Dahyabhai <[email protected]>
When chown()ing the upper directory to match the lower directory, if the ownership of the lower directory is the overflow UID:GID, ignore EINVAL. Signed-off-by: Nalin Dahyabhai <[email protected]>
Mount a read-write overlay directory over the build context directory to restore the ability to use it as a covert cache of sorts during the lifetime of the build, but in a way that still ensures that we don't modify the real build context directory. N.B.: builds where FROM in one stage referenced a relative path which had been written to a bind-mounted default build context directory by an earlier stage broke when we started making those bind mounts into overlays to prevent/discard modifications to that directory, and while this extends the lifetime of that overlay so that it's consistent throughout the build, those relative path names are still going to point to the wrong location. Since we need to determine SELinux labeling before mounting the overlay, go ahead and calculate the labels to use before creating the first builder, and remove the logic that had whichever stage thought it was the first one set them in its parent object for use by other stages, in what was probably a racey way. Signed-off-by: Nalin Dahyabhai <[email protected]>
Try to limit which image transports we accept in stages, and scope the ones that use path names to the context directory. At some point anything that isn't an image ID or pullable spec should start being rejected. Signed-off-by: Nalin Dahyabhai <[email protected]>
Add a missing "not" to an error message. Signed-off-by: Nalin Dahyabhai <[email protected]>
5b05378
to
d349c14
Compare
What type of PR is this?
/kind feature
What this PR does / why we need it:
Change how we handle bind mounts of the build context directory from using a different upper for each read-write mount into it, to using one that lasts the duration of the full build.
We broke workflows which wrote content to the build context in one stage and then attempted to use archive or layout locations in the build context in a subsequent stage when we fixed CVE-2024-11218, and this should get them working again. Because that content was often addressed using relative path names which are no longer correct for the written location, we try to compensate by rewriting some types of references and straight-up rejecting some others.
How to verify it
New integration test! And some updated ones, too!
Which issue(s) this PR fixes:
Proposed fix for #5952.
Special notes for your reviewer:
Does this PR introduce a user-facing change?