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

buildah commands that don't involve building containers at all run through unshare #5750

Open
AdamWill opened this issue Sep 20, 2024 · 5 comments

Comments

@AdamWill
Copy link

Description

This is yet another in the series of 'issues to do with running buildah in a locked-down container' - see #4563 , #1901 - but with a twist: we want to use buildah to do things that don't involve building containers at all, but those commands still run through unshare. @terinjokes also noted this in #1901 (comment) .

@jeremycline and I are working on improving Fedora's container registry publication. All this needs to do is take some already-built container images from a Fedora compose, create a multiarch manifest, and push the images and the manifest to some registries. The only tools we've found for doing this are buildah and podman. We have the code for this all written. But when we try to deploy it in an openshift container (which is where we want to deploy it), it blows up because unshare doesn't work. Well, sure, it doesn't, and we don't really want to mess around with the container security stuff to allow it, because we shouldn't need it to do this. Commands which just create manifests and push images to registries should not need to run through isolation; they're just writing trivial JSON and making web API calls. (podman appears to have basically the same problem as buildah).

We would happily use a different tool for this if we could find one that just does this and avoids the mess, but we can't (suggestions welcome). We really don't want to have to write one.

Steps to reproduce the issue:

  1. Create a bog-standard Fedora container in Fedora openshift, with buildah in it
  2. Try and run buildah login or buildah manifest create or buildah manifest push

Describe the results you received:

sh-5.2$ HOME=/tmp/whatever buildah login
WARN[0000] Reading allowed ID mappings: reading subuid mappings for user "1001340000" and subgid mappings for group "1001340000": no subuid ranges found for user "1001340000" in /etc/subuid 
WARN[0000] Found no UID ranges set aside for user "1001340000" in /etc/subuid. 
WARN[0000] Found no GID ranges set aside for user "1001340000" in /etc/subgid. 
Error during unshare(CLONE_NEWUSER): Function not implemented
ERRO[0000] parsing PID "": strconv.Atoi: parsing "": invalid syntax 
ERRO[0000] (Unable to determine exit status)            
sh-5.2$ 

Describe the results you expected:
successful login

@AdamWill
Copy link
Author

The HOME=/tmp/whatever is needed because without that buildah has a fit about ~/.config not being owned by the current user, btw.

@AdamWill
Copy link
Author

Ugh. I guess #3259 is a complicating factor here?

@AdamWill
Copy link
Author

Here's a kinda silly 'fix' for this, I guess...

diff --git a/cmd/buildah/main.go b/cmd/buildah/main.go
index 524d87b32..df42a82f5 100644
--- a/cmd/buildah/main.go
+++ b/cmd/buildah/main.go
@@ -40,6 +40,7 @@ type globalFlags struct {
        MemoryProfile              string
        UserShortNameAliasConfPath string
        CgroupManager              string
+       NoUnshare                  bool
 }
 
 var rootCmd = &cobra.Command{
@@ -105,6 +106,7 @@ func init() {
        rootCmd.PersistentFlags().StringVar(&globalFlagResults.LogLevel, logLevel, "warn", `the log level to be used, one of "trace", "debug", "info", "warn", "error", "fatal", or "panic"`)
        rootCmd.PersistentFlags().StringVar(&globalFlagResults.CPUProfile, "cpu-profile", "", "`file` to write CPU profile")
        rootCmd.PersistentFlags().StringVar(&globalFlagResults.MemoryProfile, "memory-profile", "", "`file` to write memory profile")
+       rootCmd.PersistentFlags().BoolVar(&globalFlagResults.NoUnshare, "no-unshare", false, "disable user namespace re-exec when unprivileged (for running non-build commands like pull, push and manifest in locked-down containers)")
 
        if err := rootCmd.PersistentFlags().MarkHidden("cpu-profile"); err != nil {
                logrus.Fatalf("unable to mark cpu-profile flag as hidden: %v", err)
@@ -145,6 +147,13 @@ func before(cmd *cobra.Command) error {
        case "", "help", "version", "mount":
                return nil
        }
+       if globalFlagResults.NoUnshare {
+               switch cmd.Use {
+               case "add", "build", "commit", "copy", "from", "mkcw", "run", "umount", "unshare":
+                       return fmt.Errorf("command %s cannot be used with --no-unshare", cmd.Use)
+               }
+               return nil
+       }
        debugCapabilities()
        unshare.MaybeReexecUsingUserNamespace(false)
        if globalFlagResults.CPUProfile != "" {

@rhatdan
Copy link
Member

rhatdan commented Sep 23, 2024

Let's just add the ones that make no sense to unshare to the line above:

switch cmd.Use {
case "", "help", "version", "mount":
	return nil
}

@rhatdan rhatdan closed this as completed Sep 23, 2024
@rhatdan rhatdan reopened this Sep 23, 2024
rhatdan added a commit to rhatdan/buildah that referenced this issue Sep 23, 2024
Copy link

A friendly reminder that this issue had no activity for 30 days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants