summaryrefslogtreecommitdiff
path: root/vendor/github.com/projectatomic/buildah/run.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/projectatomic/buildah/run.go')
-rw-r--r--vendor/github.com/projectatomic/buildah/run.go154
1 files changed, 115 insertions, 39 deletions
diff --git a/vendor/github.com/projectatomic/buildah/run.go b/vendor/github.com/projectatomic/buildah/run.go
index 97d247fdc..e111c5207 100644
--- a/vendor/github.com/projectatomic/buildah/run.go
+++ b/vendor/github.com/projectatomic/buildah/run.go
@@ -21,7 +21,6 @@ import (
"github.com/containernetworking/cni/libcni"
"github.com/containers/storage/pkg/ioutils"
"github.com/containers/storage/pkg/reexec"
- "github.com/docker/docker/profiles/seccomp"
units "github.com/docker/go-units"
digest "github.com/opencontainers/go-digest"
"github.com/opencontainers/runtime-spec/specs-go"
@@ -103,10 +102,34 @@ type IDMappingOptions struct {
GIDMap []specs.LinuxIDMapping
}
+// Isolation provides a way to specify whether we're supposed to use a proper
+// OCI runtime, or some other method for running commands.
+type Isolation int
+
+const (
+ // IsolationDefault is whatever we think will work best.
+ IsolationDefault Isolation = iota
+ // IsolationOCI is a proper OCI runtime.
+ IsolationOCI
+)
+
+// String converts a Isolation into a string.
+func (i Isolation) String() string {
+ switch i {
+ case IsolationDefault:
+ return "IsolationDefault"
+ case IsolationOCI:
+ return "IsolationOCI"
+ }
+ return fmt.Sprintf("unrecognized isolation type %d", i)
+}
+
// RunOptions can be used to alter how a command is run in the container.
type RunOptions struct {
// Hostname is the hostname we set for the running container.
Hostname string
+ // Isolation is either IsolationDefault or IsolationOCI.
+ Isolation Isolation
// Runtime is the name of the command to run. It should accept the same arguments
// that runc does, and produce similar output.
Runtime string
@@ -167,7 +190,7 @@ type RunOptions struct {
// DefaultNamespaceOptions returns the default namespace settings from the
// runtime-tools generator library.
-func DefaultNamespaceOptions() NamespaceOptions {
+func DefaultNamespaceOptions() (NamespaceOptions, error) {
options := NamespaceOptions{
{Name: string(specs.CgroupNamespace), Host: true},
{Name: string(specs.IPCNamespace), Host: true},
@@ -177,8 +200,11 @@ func DefaultNamespaceOptions() NamespaceOptions {
{Name: string(specs.UserNamespace), Host: true},
{Name: string(specs.UTSNamespace), Host: true},
}
- g := generate.New()
- spec := g.Spec()
+ g, err := generate.New("linux")
+ if err != nil {
+ return options, err
+ }
+ spec := g.Config
if spec.Linux != nil {
for _, ns := range spec.Linux.Namespaces {
options.AddOrReplace(NamespaceOption{
@@ -187,7 +213,7 @@ func DefaultNamespaceOptions() NamespaceOptions {
})
}
}
- return options
+ return options, nil
}
// Find the configuration for the namespace of the given type. If there are
@@ -658,30 +684,6 @@ func setupCapabilities(g *generate.Generator, firstAdds, firstDrops, secondAdds,
return nil
}
-func setupSeccomp(spec *specs.Spec, seccompProfilePath string) error {
- switch seccompProfilePath {
- case "unconfined":
- spec.Linux.Seccomp = nil
- case "":
- seccompConfig, err := seccomp.GetDefaultProfile(spec)
- if err != nil {
- return errors.Wrapf(err, "loading default seccomp profile failed")
- }
- spec.Linux.Seccomp = seccompConfig
- default:
- seccompProfile, err := ioutil.ReadFile(seccompProfilePath)
- if err != nil {
- return errors.Wrapf(err, "opening seccomp profile (%s) failed", seccompProfilePath)
- }
- seccompConfig, err := seccomp.LoadProfile(string(seccompProfile), spec)
- if err != nil {
- return errors.Wrapf(err, "loading seccomp profile (%s) failed", seccompProfilePath)
- }
- spec.Linux.Seccomp = seccompConfig
- }
- return nil
-}
-
func setupApparmor(spec *specs.Spec, apparmorProfile string) error {
spec.Process.ApparmorProfile = apparmorProfile
return nil
@@ -795,6 +797,53 @@ func setupNamespaces(g *generate.Generator, namespaceOptions NamespaceOptions, i
return configureNetwork, configureNetworks, configureUTS, nil
}
+// Search for a command that isn't given as an absolute path using the $PATH
+// under the rootfs. We can't resolve absolute symbolic links without
+// chroot()ing, which we may not be able to do, so just accept a link as a
+// valid resolution.
+func runLookupPath(g *generate.Generator, command []string) []string {
+ // Look for the configured $PATH.
+ spec := g.Spec()
+ envPath := ""
+ for i := range spec.Process.Env {
+ if strings.HasPrefix(spec.Process.Env[i], "PATH=") {
+ envPath = spec.Process.Env[i]
+ }
+ }
+ // If there is no configured $PATH, supply one.
+ if envPath == "" {
+ defaultPath := "/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin"
+ envPath = "PATH=" + defaultPath
+ g.AddProcessEnv("PATH", defaultPath)
+ }
+ // No command, nothing to do.
+ if len(command) == 0 {
+ return command
+ }
+ // Command is already an absolute path, use it as-is.
+ if filepath.IsAbs(command[0]) {
+ return command
+ }
+ // For each element in the PATH,
+ for _, pathEntry := range filepath.SplitList(envPath[5:]) {
+ // if it's the empty string, it's ".", which is the Cwd,
+ if pathEntry == "" {
+ pathEntry = spec.Process.Cwd
+ }
+ // build the absolute path which it might be,
+ candidate := filepath.Join(pathEntry, command[0])
+ // check if it's there,
+ if fi, err := os.Lstat(filepath.Join(spec.Root.Path, candidate)); fi != nil && err == nil {
+ // and if it's not a directory, and either a symlink or executable,
+ if !fi.IsDir() && ((fi.Mode()&os.ModeSymlink != 0) || (fi.Mode()&0111 != 0)) {
+ // use that.
+ return append([]string{candidate}, command[1:]...)
+ }
+ }
+ }
+ return command
+}
+
// Run runs the specified command in the container's root filesystem.
func (b *Builder) Run(command []string, options RunOptions) error {
var user specs.User
@@ -814,9 +863,14 @@ func (b *Builder) Run(command []string, options RunOptions) error {
logrus.Errorf("error removing %q: %v", path, err2)
}
}()
- gp := generate.New()
+ gp, err := generate.New("linux")
+ if err != nil {
+ return err
+ }
+
g := &gp
+ g.ClearProcessEnv()
for _, envSpec := range append(b.Env(), options.Env...) {
env := strings.SplitN(envSpec, "=", 2)
if len(env) > 1 {
@@ -824,6 +878,10 @@ func (b *Builder) Run(command []string, options RunOptions) error {
}
}
+ for src, dest := range b.Args {
+ g.AddProcessEnv(src, dest)
+ }
+
if b.CommonBuildOpts == nil {
return errors.Errorf("Invalid format on container you must recreate the container")
}
@@ -832,11 +890,6 @@ func (b *Builder) Run(command []string, options RunOptions) error {
return err
}
- if len(command) > 0 {
- g.SetProcessArgs(command)
- } else {
- g.SetProcessArgs(nil)
- }
if options.WorkingDir != "" {
g.SetProcessCwd(options.WorkingDir)
} else if b.WorkDir() != "" {
@@ -853,15 +906,25 @@ func (b *Builder) Run(command []string, options RunOptions) error {
logrus.Errorf("error unmounting container: %v", err2)
}
}()
+ g.SetRootPath(mountPoint)
+ if len(command) > 0 {
+ command = runLookupPath(g, command)
+ g.SetProcessArgs(command)
+ } else {
+ g.SetProcessArgs(nil)
+ }
setupMaskedPaths(g)
setupReadOnlyPaths(g)
- g.SetRootPath(mountPoint)
-
setupTerminal(g, options.Terminal, options.TerminalSize)
- namespaceOptions := DefaultNamespaceOptions()
+ defaultNamespaceOptions, err := DefaultNamespaceOptions()
+ if err != nil {
+ return err
+ }
+
+ namespaceOptions := defaultNamespaceOptions
namespaceOptions.AddOrReplace(b.NamespaceOptions...)
namespaceOptions.AddOrReplace(options.NamespaceOptions...)
@@ -967,7 +1030,20 @@ func (b *Builder) Run(command []string, options RunOptions) error {
}
}
- return b.runUsingRuntimeSubproc(options, configureNetwork, configureNetworks, spec, mountPoint, path, Package+"-"+filepath.Base(path))
+ isolation := options.Isolation
+ if isolation == IsolationDefault {
+ isolation = b.Isolation
+ if isolation == IsolationDefault {
+ isolation = IsolationOCI
+ }
+ }
+ switch isolation {
+ case IsolationOCI:
+ err = b.runUsingRuntimeSubproc(options, configureNetwork, configureNetworks, spec, mountPoint, path, Package+"-"+filepath.Base(path))
+ default:
+ err = errors.Errorf("don't know how to run this command")
+ }
+ return err
}
type runUsingRuntimeSubprocOptions struct {