| 
									
										
										
										
											2022-02-14 17:05:46 +08:00
										 |  |  | //go:build linux
 | 
					
						
							| 
									
										
										
										
											2018-06-29 22:00:38 +08:00
										 |  |  | // +build linux
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package buildah | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2022-06-22 18:48:00 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2018-06-29 22:00:38 +08:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	"os/exec" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"strconv" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"syscall" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/containers/buildah/bind" | 
					
						
							|  |  |  | 	"github.com/containers/buildah/chroot" | 
					
						
							| 
									
										
										
										
											2020-10-31 17:58:59 +08:00
										 |  |  | 	"github.com/containers/buildah/copier" | 
					
						
							| 
									
										
										
										
											2021-02-07 06:49:40 +08:00
										 |  |  | 	"github.com/containers/buildah/define" | 
					
						
							| 
									
										
										
										
											2021-10-18 13:51:51 +08:00
										 |  |  | 	"github.com/containers/buildah/internal" | 
					
						
							|  |  |  | 	internalParse "github.com/containers/buildah/internal/parse" | 
					
						
							| 
									
										
										
										
											2019-04-29 21:41:18 +08:00
										 |  |  | 	"github.com/containers/buildah/pkg/overlay" | 
					
						
							| 
									
										
										
										
											2021-09-28 19:20:36 +08:00
										 |  |  | 	"github.com/containers/buildah/pkg/parse" | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	"github.com/containers/buildah/util" | 
					
						
							| 
									
										
										
										
											2022-05-12 21:42:05 +08:00
										 |  |  | 	"github.com/containers/common/libnetwork/resolvconf" | 
					
						
							| 
									
										
										
										
											2022-01-06 04:36:49 +08:00
										 |  |  | 	nettypes "github.com/containers/common/libnetwork/types" | 
					
						
							| 
									
										
										
										
											2020-02-19 03:50:08 +08:00
										 |  |  | 	"github.com/containers/common/pkg/capabilities" | 
					
						
							| 
									
										
										
										
											2021-01-25 22:32:56 +08:00
										 |  |  | 	"github.com/containers/common/pkg/chown" | 
					
						
							| 
									
										
										
										
											2020-02-08 01:54:18 +08:00
										 |  |  | 	"github.com/containers/common/pkg/config" | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 	"github.com/containers/common/pkg/hooks" | 
					
						
							|  |  |  | 	hooksExec "github.com/containers/common/pkg/hooks/exec" | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	"github.com/containers/storage/pkg/idtools" | 
					
						
							|  |  |  | 	"github.com/containers/storage/pkg/ioutils" | 
					
						
							| 
									
										
										
										
											2022-10-19 08:13:05 +08:00
										 |  |  | 	"github.com/containers/storage/pkg/lockfile" | 
					
						
							| 
									
										
										
										
											2024-12-14 05:55:59 +08:00
										 |  |  | 	"github.com/containers/storage/pkg/mount" | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	"github.com/containers/storage/pkg/stringid" | 
					
						
							| 
									
										
										
										
											2020-03-31 21:56:18 +08:00
										 |  |  | 	"github.com/containers/storage/pkg/unshare" | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	"github.com/docker/go-units" | 
					
						
							|  |  |  | 	"github.com/opencontainers/runtime-spec/specs-go" | 
					
						
							| 
									
										
										
										
											2019-09-07 03:07:18 +08:00
										 |  |  | 	spec "github.com/opencontainers/runtime-spec/specs-go" | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	"github.com/opencontainers/runtime-tools/generate" | 
					
						
							|  |  |  | 	"github.com/opencontainers/selinux/go-selinux/label" | 
					
						
							|  |  |  | 	"github.com/sirupsen/logrus" | 
					
						
							|  |  |  | 	"golang.org/x/sys/unix" | 
					
						
							| 
									
										
										
										
											2018-06-29 22:00:38 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-24 23:40:57 +08:00
										 |  |  | // ContainerDevices is an alias for a slice of github.com/opencontainers/runc/libcontainer/configs.Device structures.
 | 
					
						
							| 
									
										
										
										
											2021-02-07 06:49:40 +08:00
										 |  |  | type ContainerDevices define.ContainerDevices | 
					
						
							| 
									
										
										
										
											2020-09-24 23:40:57 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-18 20:04:53 +08:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	// We dont want to remove destinations with /etc, /dev, /sys,
 | 
					
						
							|  |  |  | 	// /proc as rootfs already contains these files and unionfs
 | 
					
						
							|  |  |  | 	// will create a `whiteout` i.e `.wh` files on removal of
 | 
					
						
							|  |  |  | 	// overlapping files from these directories.  everything other
 | 
					
						
							|  |  |  | 	// than these will be cleaned up
 | 
					
						
							|  |  |  | 	nonCleanablePrefixes = []string{ | 
					
						
							|  |  |  | 		"/etc", "/dev", "/sys", "/proc", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-29 22:00:38 +08:00
										 |  |  | func setChildProcess() error { | 
					
						
							|  |  |  | 	if err := unix.Prctl(unix.PR_SET_CHILD_SUBREAPER, uintptr(1), 0, 0, 0); err != nil { | 
					
						
							|  |  |  | 		fmt.Fprintf(os.Stderr, "prctl(PR_SET_CHILD_SUBREAPER, 1): %v\n", err) | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Run runs the specified command in the container's root filesystem.
 | 
					
						
							|  |  |  | func (b *Builder) Run(command []string, options RunOptions) error { | 
					
						
							| 
									
										
										
										
											2022-11-15 00:22:45 +08:00
										 |  |  | 	p, err := os.MkdirTemp("", define.Package) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-10-15 17:16:50 +08:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	// On some hosts like AH, /tmp is a symlink and we need an
 | 
					
						
							|  |  |  | 	// absolute path.
 | 
					
						
							|  |  |  | 	path, err := filepath.EvalSymlinks(p) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-10-15 17:16:50 +08:00
										 |  |  | 		return err | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	logrus.Debugf("using %q to hold bundle data", path) | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err2 := os.RemoveAll(path); err2 != nil { | 
					
						
							| 
									
										
										
										
											2021-05-08 01:38:44 +08:00
										 |  |  | 			options.Logger.Error(err2) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gp, err := generate.New("linux") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 		return fmt.Errorf("generating new 'linux' runtime spec: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	g := &gp | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	isolation := options.Isolation | 
					
						
							| 
									
										
										
										
											2021-02-07 06:49:40 +08:00
										 |  |  | 	if isolation == define.IsolationDefault { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		isolation = b.Isolation | 
					
						
							| 
									
										
										
										
											2021-02-07 06:49:40 +08:00
										 |  |  | 		if isolation == define.IsolationDefault { | 
					
						
							|  |  |  | 			isolation = define.IsolationOCI | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := checkAndOverrideIsolationOptions(isolation, &options); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-27 23:33:35 +08:00
										 |  |  | 	// hardwire the environment to match docker build to avoid subtle and hard-to-debug differences due to containers.conf
 | 
					
						
							|  |  |  | 	b.configureEnvironment(g, options, []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if b.CommonBuildOpts == nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 		return fmt.Errorf("invalid format on container you must recreate the container") | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := addCommonOptsToSpec(b.CommonBuildOpts, g); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-07 20:06:12 +08:00
										 |  |  | 	workDir := b.WorkDir() | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	if options.WorkingDir != "" { | 
					
						
							|  |  |  | 		g.SetProcessCwd(options.WorkingDir) | 
					
						
							| 
									
										
										
										
											2022-12-07 20:06:12 +08:00
										 |  |  | 		workDir = options.WorkingDir | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} else if b.WorkDir() != "" { | 
					
						
							|  |  |  | 		g.SetProcessCwd(b.WorkDir()) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	setupSelinux(g, b.ProcessLabel, b.MountLabel) | 
					
						
							|  |  |  | 	mountPoint, err := b.Mount(b.MountLabel) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 		return fmt.Errorf("mounting container %q: %w", b.ContainerID, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							|  |  |  | 		if err := b.Unmount(); err != nil { | 
					
						
							| 
									
										
										
										
											2021-05-08 01:38:44 +08:00
										 |  |  | 			options.Logger.Errorf("error unmounting container: %v", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 	g.SetRootPath(mountPoint) | 
					
						
							|  |  |  | 	if len(command) > 0 { | 
					
						
							|  |  |  | 		command = runLookupPath(g, command) | 
					
						
							|  |  |  | 		g.SetProcessArgs(command) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		g.SetProcessArgs(nil) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-24 18:23:32 +08:00
										 |  |  | 	// Mount devices if any and if session is rootless attempt a bind-mount
 | 
					
						
							|  |  |  | 	// just like podman.
 | 
					
						
							|  |  |  | 	if unshare.IsRootless() { | 
					
						
							|  |  |  | 		// We are going to create bind mounts for devices
 | 
					
						
							|  |  |  | 		// but we need to make sure that we don't override
 | 
					
						
							|  |  |  | 		// anything which is already in OCI spec.
 | 
					
						
							|  |  |  | 		mounts := make(map[string]interface{}) | 
					
						
							|  |  |  | 		for _, m := range g.Mounts() { | 
					
						
							|  |  |  | 			mounts[m.Destination] = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		newMounts := []spec.Mount{} | 
					
						
							|  |  |  | 		for _, d := range b.Devices { | 
					
						
							|  |  |  | 			// Default permission is read-only.
 | 
					
						
							|  |  |  | 			perm := "ro" | 
					
						
							|  |  |  | 			// Get permission configured for this device but only process `write`
 | 
					
						
							|  |  |  | 			// permission in rootless since `mknod` is not supported anyways.
 | 
					
						
							|  |  |  | 			if strings.Contains(string(d.Rule.Permissions), "w") { | 
					
						
							|  |  |  | 				perm = "rw" | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			devMnt := spec.Mount{ | 
					
						
							|  |  |  | 				Destination: d.Destination, | 
					
						
							|  |  |  | 				Type:        parse.TypeBind, | 
					
						
							|  |  |  | 				Source:      d.Source, | 
					
						
							|  |  |  | 				Options:     []string{"slave", "nosuid", "noexec", perm, "rbind"}, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Podman parity: podman skips these two devices hence we do the same.
 | 
					
						
							|  |  |  | 			if d.Path == "/dev/ptmx" || strings.HasPrefix(d.Path, "/dev/tty") { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Device is already in OCI spec do not re-mount.
 | 
					
						
							|  |  |  | 			if _, found := mounts[d.Path]; found { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			newMounts = append(newMounts, devMnt) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		g.Config.Mounts = append(newMounts, g.Config.Mounts...) | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		for _, d := range b.Devices { | 
					
						
							|  |  |  | 			sDev := spec.LinuxDevice{ | 
					
						
							|  |  |  | 				Type:     string(d.Type), | 
					
						
							|  |  |  | 				Path:     d.Path, | 
					
						
							|  |  |  | 				Major:    d.Major, | 
					
						
							|  |  |  | 				Minor:    d.Minor, | 
					
						
							|  |  |  | 				FileMode: &d.FileMode, | 
					
						
							|  |  |  | 				UID:      &d.Uid, | 
					
						
							|  |  |  | 				GID:      &d.Gid, | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			g.AddDevice(sDev) | 
					
						
							|  |  |  | 			g.AddLinuxResourcesDevice(true, string(d.Type), &d.Major, &d.Minor, string(d.Permissions)) | 
					
						
							| 
									
										
										
										
											2019-09-07 03:07:18 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	setupMaskedPaths(g) | 
					
						
							|  |  |  | 	setupReadOnlyPaths(g) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	setupTerminal(g, options.Terminal, options.TerminalSize) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-27 17:13:35 +08:00
										 |  |  | 	configureNetwork, configureNetworks, err := b.configureNamespaces(g, &options) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-19 23:43:02 +08:00
										 |  |  | 	// rootless and networks are not supported
 | 
					
						
							|  |  |  | 	if len(configureNetworks) > 0 && isolation == IsolationOCIRootless { | 
					
						
							|  |  |  | 		return errors.New("cannot use networks as rootless") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-16 06:40:15 +08:00
										 |  |  | 	homeDir, err := b.configureUIDGID(g, mountPoint, options) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-04 19:04:16 +08:00
										 |  |  | 	g.SetProcessNoNewPrivileges(b.CommonBuildOpts.NoNewPrivileges) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	g.SetProcessApparmorProfile(b.CommonBuildOpts.ApparmorProfile) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Now grab the spec from the generator.  Set the generator to nil so that future contributors
 | 
					
						
							|  |  |  | 	// will quickly be able to tell that they're supposed to be modifying the spec directly from here.
 | 
					
						
							|  |  |  | 	spec := g.Config | 
					
						
							|  |  |  | 	g = nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Set the seccomp configuration using the specified profile name.  Some syscalls are
 | 
					
						
							|  |  |  | 	// allowed if certain capabilities are to be granted (example: CAP_SYS_CHROOT and chroot),
 | 
					
						
							|  |  |  | 	// so we sorted out the capabilities lists first.
 | 
					
						
							|  |  |  | 	if err = setupSeccomp(spec, b.CommonBuildOpts.SeccompProfilePath); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 18:37:57 +08:00
										 |  |  | 	uid, gid := spec.Process.User.UID, spec.Process.User.GID | 
					
						
							|  |  |  | 	if spec.Linux != nil { | 
					
						
							|  |  |  | 		uid, gid, err = util.GetHostIDs(spec.Linux.UIDMappings, spec.Linux.GIDMappings, uid, gid) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-23 18:37:57 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	idPair := &idtools.IDPair{UID: int(uid), GID: int(gid)} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-31 17:58:59 +08:00
										 |  |  | 	mode := os.FileMode(0755) | 
					
						
							|  |  |  | 	coptions := copier.MkdirOptions{ | 
					
						
							| 
									
										
										
										
											2022-03-23 18:37:57 +08:00
										 |  |  | 		ChownNew: idPair, | 
					
						
							| 
									
										
										
										
											2020-10-31 17:58:59 +08:00
										 |  |  | 		ChmodNew: &mode, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-11-06 01:46:21 +08:00
										 |  |  | 	if err := copier.Mkdir(mountPoint, filepath.Join(mountPoint, spec.Process.Cwd), coptions); err != nil { | 
					
						
							| 
									
										
										
										
											2020-10-31 17:58:59 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	bindFiles := make(map[string]string) | 
					
						
							|  |  |  | 	volumes := b.Volumes() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-23 18:37:57 +08:00
										 |  |  | 	// Figure out who owns files that will appear to be owned by UID/GID 0 in the container.
 | 
					
						
							|  |  |  | 	rootUID, rootGID, err := util.GetHostRootIDs(spec) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	rootIDPair := &idtools.IDPair{UID: int(rootUID), GID: int(rootGID)} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-19 16:55:16 +08:00
										 |  |  | 	hostFile := "" | 
					
						
							|  |  |  | 	if !options.NoHosts && !contains(volumes, config.DefaultHostsFile) && options.ConfigureNetwork != define.NetworkDisabled { | 
					
						
							|  |  |  | 		hostFile, err = b.generateHosts(path, rootIDPair, mountPoint) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-04-19 16:55:16 +08:00
										 |  |  | 		bindFiles[config.DefaultHostsFile] = hostFile | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-21 15:35:56 +08:00
										 |  |  | 	// generate /etc/hostname if the user intentionally did not override
 | 
					
						
							|  |  |  | 	if !(contains(volumes, "/etc/hostname")) { | 
					
						
							|  |  |  | 		if _, ok := bindFiles["/etc/hostname"]; !ok { | 
					
						
							|  |  |  | 			hostFile, err := b.generateHostname(path, spec.Hostname, rootIDPair) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			// Bind /etc/hostname
 | 
					
						
							|  |  |  | 			bindFiles["/etc/hostname"] = hostFile | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-12 21:42:05 +08:00
										 |  |  | 	if !contains(volumes, resolvconf.DefaultResolvConf) && options.ConfigureNetwork != define.NetworkDisabled && !(len(b.CommonBuildOpts.DNSServers) == 1 && strings.ToLower(b.CommonBuildOpts.DNSServers[0]) == "none") { | 
					
						
							|  |  |  | 		resolvFile, err := b.addResolvConf(path, rootIDPair, b.CommonBuildOpts.DNSServers, b.CommonBuildOpts.DNSSearch, b.CommonBuildOpts.DNSOptions, spec.Linux.Namespaces) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-05-12 21:42:05 +08:00
										 |  |  | 		bindFiles[resolvconf.DefaultResolvConf] = resolvFile | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-09-06 04:54:40 +08:00
										 |  |  | 	// Empty file, so no need to recreate if it exists
 | 
					
						
							|  |  |  | 	if _, ok := bindFiles["/run/.containerenv"]; !ok { | 
					
						
							|  |  |  | 		containerenvPath := filepath.Join(path, "/run/.containerenv") | 
					
						
							| 
									
										
										
										
											2020-10-15 17:16:50 +08:00
										 |  |  | 		if err = os.MkdirAll(filepath.Dir(containerenvPath), 0755); err != nil { | 
					
						
							| 
									
										
										
										
											2019-09-06 04:54:40 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-24 08:07:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		rootless := 0 | 
					
						
							|  |  |  | 		if unshare.IsRootless() { | 
					
						
							|  |  |  | 			rootless = 1 | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		// Populate the .containerenv with container information
 | 
					
						
							| 
									
										
										
										
											2022-04-05 05:27:24 +08:00
										 |  |  | 		containerenv := fmt.Sprintf(` | 
					
						
							| 
									
										
										
										
											2020-11-24 08:07:50 +08:00
										 |  |  | engine="buildah-%s" | 
					
						
							|  |  |  | name=%q | 
					
						
							|  |  |  | id=%q | 
					
						
							|  |  |  | image=%q | 
					
						
							|  |  |  | imageid=%q | 
					
						
							|  |  |  | rootless=%d | 
					
						
							| 
									
										
										
										
											2021-02-07 06:49:40 +08:00
										 |  |  | `, define.Version, b.Container, b.ContainerID, b.FromImage, b.FromImageID, rootless) | 
					
						
							| 
									
										
										
										
											2020-11-24 08:07:50 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if err = ioutils.AtomicWriteFile(containerenvPath, []byte(containerenv), 0755); err != nil { | 
					
						
							| 
									
										
										
										
											2019-09-06 04:54:40 +08:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err := label.Relabel(containerenvPath, b.MountLabel, false); err != nil { | 
					
						
							| 
									
										
										
										
											2020-10-15 17:16:50 +08:00
										 |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2019-09-06 04:54:40 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		bindFiles["/run/.containerenv"] = containerenvPath | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-05-27 10:47:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-22 18:48:00 +08:00
										 |  |  | 	// Setup OCI hooks
 | 
					
						
							|  |  |  | 	_, err = b.setupOCIHooks(spec, (len(options.Mounts) > 0 || len(volumes) > 0)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 		return fmt.Errorf("unable to setup OCI hooks: %w", err) | 
					
						
							| 
									
										
										
										
											2022-06-22 18:48:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-27 10:47:30 +08:00
										 |  |  | 	runMountInfo := runMountInfo{ | 
					
						
							| 
									
										
										
										
											2022-12-07 20:06:12 +08:00
										 |  |  | 		WorkDir:          workDir, | 
					
						
							| 
									
										
										
										
											2022-05-27 10:47:30 +08:00
										 |  |  | 		ContextDir:       options.ContextDir, | 
					
						
							|  |  |  | 		Secrets:          options.Secrets, | 
					
						
							|  |  |  | 		SSHSources:       options.SSHSources, | 
					
						
							|  |  |  | 		StageMountPoints: options.StageMountPoints, | 
					
						
							|  |  |  | 		SystemContext:    options.SystemContext, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	runArtifacts, err := b.setupMounts(mountPoint, spec, path, options.Mounts, bindFiles, volumes, b.CommonBuildOpts.Volumes, options.RunMounts, runMountInfo) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 		return fmt.Errorf("resolving mountpoints for container %q: %w", b.ContainerID, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-07-26 14:07:23 +08:00
										 |  |  | 	if runArtifacts.SSHAuthSock != "" { | 
					
						
							|  |  |  | 		sshenv := "SSH_AUTH_SOCK=" + runArtifacts.SSHAuthSock | 
					
						
							|  |  |  | 		spec.Process.Env = append(spec.Process.Env, sshenv) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-04-17 06:21:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-18 13:51:51 +08:00
										 |  |  | 	// following run was called from `buildah run`
 | 
					
						
							|  |  |  | 	// and some images were mounted for this run
 | 
					
						
							|  |  |  | 	// add them to cleanup artifacts
 | 
					
						
							|  |  |  | 	if len(options.ExternalImageMounts) > 0 { | 
					
						
							|  |  |  | 		runArtifacts.MountedImages = append(runArtifacts.MountedImages, options.ExternalImageMounts...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-17 06:21:31 +08:00
										 |  |  | 	defer func() { | 
					
						
							| 
									
										
										
										
											2024-11-07 06:22:49 +08:00
										 |  |  | 		if err := b.cleanupRunMounts(mountPoint, runArtifacts); err != nil { | 
					
						
							| 
									
										
										
										
											2021-10-18 13:51:51 +08:00
										 |  |  | 			options.Logger.Errorf("unable to cleanup run mounts %v", err) | 
					
						
							| 
									
										
										
										
											2021-04-17 06:21:31 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-29 21:41:18 +08:00
										 |  |  | 	defer b.cleanupTempVolumes() | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	switch isolation { | 
					
						
							| 
									
										
										
										
											2021-02-07 06:49:40 +08:00
										 |  |  | 	case define.IsolationOCI: | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		var moreCreateArgs []string | 
					
						
							|  |  |  | 		if options.NoPivot { | 
					
						
							| 
									
										
										
										
											2022-03-18 05:33:50 +08:00
										 |  |  | 			moreCreateArgs = append(moreCreateArgs, "--no-pivot") | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-04-19 16:55:16 +08:00
										 |  |  | 		err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, configureNetworks, moreCreateArgs, spec, | 
					
						
							|  |  |  | 			mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostFile) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	case IsolationChroot: | 
					
						
							| 
									
										
										
										
											2019-05-16 06:40:15 +08:00
										 |  |  | 		err = chroot.RunUsingChroot(spec, path, homeDir, options.Stdin, options.Stdout, options.Stderr) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	case IsolationOCIRootless: | 
					
						
							|  |  |  | 		moreCreateArgs := []string{"--no-new-keyring"} | 
					
						
							|  |  |  | 		if options.NoPivot { | 
					
						
							|  |  |  | 			moreCreateArgs = append(moreCreateArgs, "--no-pivot") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-04-19 16:55:16 +08:00
										 |  |  | 		err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, configureNetworks, moreCreateArgs, spec, | 
					
						
							|  |  |  | 			mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostFile) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	default: | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 		err = errors.New("don't know how to run this command") | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-22 18:48:00 +08:00
										 |  |  | func (b *Builder) setupOCIHooks(config *spec.Spec, hasVolumes bool) (map[string][]spec.Hook, error) { | 
					
						
							|  |  |  | 	allHooks := make(map[string][]spec.Hook) | 
					
						
							|  |  |  | 	if len(b.CommonBuildOpts.OCIHooksDir) == 0 { | 
					
						
							|  |  |  | 		if unshare.IsRootless() { | 
					
						
							|  |  |  | 			return nil, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for _, hDir := range []string{hooks.DefaultDir, hooks.OverrideDir} { | 
					
						
							|  |  |  | 			manager, err := hooks.New(context.Background(), []string{hDir}, []string{}) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-27 03:27:30 +08:00
										 |  |  | 				if errors.Is(err, os.ErrNotExist) { | 
					
						
							| 
									
										
										
										
											2022-06-22 18:48:00 +08:00
										 |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			ociHooks, err := manager.Hooks(config, b.ImageAnnotations, hasVolumes) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if len(ociHooks) > 0 || config.Hooks != nil { | 
					
						
							|  |  |  | 				logrus.Warnf("Implicit hook directories are deprecated; set --hooks-dir=%q explicitly to continue to load ociHooks from this directory", hDir) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for i, hook := range ociHooks { | 
					
						
							|  |  |  | 				allHooks[i] = hook | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		manager, err := hooks.New(context.Background(), b.CommonBuildOpts.OCIHooksDir, []string{}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		allHooks, err = manager.Hooks(config, b.ImageAnnotations, hasVolumes) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hookErr, err := hooksExec.RuntimeConfigFilter(context.Background(), allHooks["precreate"], config, hooksExec.DefaultPostKillTimeout) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		logrus.Warnf("Container: precreate hook: %v", err) | 
					
						
							|  |  |  | 		if hookErr != nil && hookErr != err { | 
					
						
							|  |  |  | 			logrus.Debugf("container: precreate hook (hook error): %v", hookErr) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return allHooks, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-02-07 06:49:40 +08:00
										 |  |  | func addCommonOptsToSpec(commonOpts *define.CommonBuildOptions, g *generate.Generator) error { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	// Resources - CPU
 | 
					
						
							|  |  |  | 	if commonOpts.CPUPeriod != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUPeriod(commonOpts.CPUPeriod) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.CPUQuota != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUQuota(commonOpts.CPUQuota) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.CPUShares != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUShares(commonOpts.CPUShares) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.CPUSetCPUs != "" { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUCpus(commonOpts.CPUSetCPUs) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.CPUSetMems != "" { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesCPUMems(commonOpts.CPUSetMems) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Resources - Memory
 | 
					
						
							|  |  |  | 	if commonOpts.Memory != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesMemoryLimit(commonOpts.Memory) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if commonOpts.MemorySwap != 0 { | 
					
						
							|  |  |  | 		g.SetLinuxResourcesMemorySwap(commonOpts.MemorySwap) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// cgroup membership
 | 
					
						
							|  |  |  | 	if commonOpts.CgroupParent != "" { | 
					
						
							|  |  |  | 		g.SetLinuxCgroupsPath(commonOpts.CgroupParent) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-08 01:54:18 +08:00
										 |  |  | 	defaultContainerConfig, err := config.Default() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 		return fmt.Errorf("failed to get container config: %w", err) | 
					
						
							| 
									
										
										
										
											2020-02-08 01:54:18 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	// Other process resource limits
 | 
					
						
							| 
									
										
										
										
											2020-02-08 01:54:18 +08:00
										 |  |  | 	if err := addRlimits(commonOpts.Ulimit, g, defaultContainerConfig.Containers.DefaultUlimits); err != nil { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	logrus.Debugf("Resources: %#v", commonOpts) | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func setupRootlessNetwork(pid int) (teardown func(), err error) { | 
					
						
							|  |  |  | 	slirp4netns, err := exec.LookPath("slirp4netns") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2020-10-15 17:16:50 +08:00
										 |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	rootlessSlirpSyncR, rootlessSlirpSyncW, err := os.Pipe() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 		return nil, fmt.Errorf("cannot create slirp4netns sync pipe: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	defer rootlessSlirpSyncR.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Be sure there are no fds inherited to slirp4netns except the sync pipe
 | 
					
						
							| 
									
										
										
										
											2022-11-15 00:22:45 +08:00
										 |  |  | 	files, err := os.ReadDir("/proc/self/fd") | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 		return nil, fmt.Errorf("cannot list open fds: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	for _, f := range files { | 
					
						
							|  |  |  | 		fd, err := strconv.Atoi(f.Name()) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 			return nil, fmt.Errorf("cannot parse fd: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if fd == int(rootlessSlirpSyncW.Fd()) { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		unix.CloseOnExec(fd) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-28 05:25:06 +08:00
										 |  |  | 	cmd := exec.Command(slirp4netns, "--mtu", "65520", "-r", "3", "-c", strconv.Itoa(pid), "tap0") | 
					
						
							| 
									
										
										
										
											2022-03-18 05:33:50 +08:00
										 |  |  | 	setPdeathsig(cmd) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	cmd.Stdin, cmd.Stdout, cmd.Stderr = nil, nil, nil | 
					
						
							|  |  |  | 	cmd.ExtraFiles = []*os.File{rootlessSlirpSyncW} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = cmd.Start() | 
					
						
							|  |  |  | 	rootlessSlirpSyncW.Close() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 		return nil, fmt.Errorf("cannot start slirp4netns: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	b := make([]byte, 1) | 
					
						
							|  |  |  | 	for { | 
					
						
							|  |  |  | 		if err := rootlessSlirpSyncR.SetDeadline(time.Now().Add(1 * time.Second)); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return nil, fmt.Errorf("setting slirp4netns pipe timeout: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if _, err := rootlessSlirpSyncR.Read(b); err == nil { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			if os.IsTimeout(err) { | 
					
						
							|  |  |  | 				// Check if the process is still running.
 | 
					
						
							|  |  |  | 				var status syscall.WaitStatus | 
					
						
							|  |  |  | 				_, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil) | 
					
						
							|  |  |  | 				if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 					return nil, fmt.Errorf("failed to read slirp4netns process status: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 				if status.Exited() || status.Signaled() { | 
					
						
							|  |  |  | 					return nil, errors.New("slirp4netns failed") | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 			return nil, fmt.Errorf("failed to read from slirp4netns sync pipe: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return func() { | 
					
						
							| 
									
										
										
										
											2019-06-18 19:37:58 +08:00
										 |  |  | 		cmd.Process.Kill() // nolint:errcheck
 | 
					
						
							|  |  |  | 		cmd.Wait()         // nolint:errcheck
 | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-19 16:55:16 +08:00
										 |  |  | func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, options RunOptions, configureNetworks []string, containerName string) (teardown func(), netStatus map[string]nettypes.StatusBlock, err error) { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	if isolation == IsolationOCIRootless { | 
					
						
							| 
									
										
										
										
											2022-04-19 16:55:16 +08:00
										 |  |  | 		teardown, err = setupRootlessNetwork(pid) | 
					
						
							|  |  |  | 		return teardown, nil, err | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-06-23 03:55:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-06 04:36:49 +08:00
										 |  |  | 	if len(configureNetworks) == 0 { | 
					
						
							|  |  |  | 		configureNetworks = []string{b.NetworkInterface.DefaultNetworkName()} | 
					
						
							| 
									
										
										
										
											2021-06-23 03:55:00 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	// Make sure we can access the container's network namespace,
 | 
					
						
							|  |  |  | 	// even after it exits, to successfully tear down the
 | 
					
						
							|  |  |  | 	// interfaces.  Ensure this by opening a handle to the network
 | 
					
						
							|  |  |  | 	// namespace, and using our copy to both configure and
 | 
					
						
							|  |  |  | 	// deconfigure it.
 | 
					
						
							|  |  |  | 	netns := fmt.Sprintf("/proc/%d/ns/net", pid) | 
					
						
							|  |  |  | 	netFD, err := unix.Open(netns, unix.O_RDONLY, 0) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 		return nil, nil, fmt.Errorf("opening network namespace: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	mynetns := fmt.Sprintf("/proc/%d/fd/%d", unix.Getpid(), netFD) | 
					
						
							| 
									
										
										
										
											2022-01-06 04:36:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	networks := make(map[string]nettypes.PerNetworkOptions, len(configureNetworks)) | 
					
						
							|  |  |  | 	for i, network := range configureNetworks { | 
					
						
							|  |  |  | 		networks[network] = nettypes.PerNetworkOptions{ | 
					
						
							|  |  |  | 			InterfaceName: fmt.Sprintf("eth%d", i), | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-01-06 04:36:49 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	opts := nettypes.NetworkOptions{ | 
					
						
							|  |  |  | 		ContainerID:   containerName, | 
					
						
							|  |  |  | 		ContainerName: containerName, | 
					
						
							|  |  |  | 		Networks:      networks, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-19 16:55:16 +08:00
										 |  |  | 	netStatus, err = b.NetworkInterface.Setup(mynetns, nettypes.SetupOptions{NetworkOptions: opts}) | 
					
						
							| 
									
										
										
										
											2022-01-06 04:36:49 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-04-19 16:55:16 +08:00
										 |  |  | 		return nil, nil, err | 
					
						
							| 
									
										
										
										
											2022-01-06 04:36:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	teardown = func() { | 
					
						
							|  |  |  | 		err := b.NetworkInterface.Teardown(mynetns, nettypes.TeardownOptions{NetworkOptions: opts}) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2022-01-06 04:36:49 +08:00
										 |  |  | 			options.Logger.Errorf("failed to cleanup network: %v", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-01-06 04:36:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-19 16:55:16 +08:00
										 |  |  | 	return teardown, netStatus, nil | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Create pipes to use for relaying stdio.
 | 
					
						
							|  |  |  | func runMakeStdioPipe(uid, gid int) ([][]int, error) { | 
					
						
							|  |  |  | 	stdioPipe := make([][]int, 3) | 
					
						
							|  |  |  | 	for i := range stdioPipe { | 
					
						
							|  |  |  | 		stdioPipe[i] = make([]int, 2) | 
					
						
							|  |  |  | 		if err := unix.Pipe(stdioPipe[i]); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return nil, fmt.Errorf("creating pipe for container FD %d: %w", i, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if err := unix.Fchown(stdioPipe[unix.Stdin][0], uid, gid); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 		return nil, fmt.Errorf("setting owner of stdin pipe descriptor: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if err := unix.Fchown(stdioPipe[unix.Stdout][1], uid, gid); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 		return nil, fmt.Errorf("setting owner of stdout pipe descriptor: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if err := unix.Fchown(stdioPipe[unix.Stderr][1], uid, gid); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 		return nil, fmt.Errorf("setting owner of stderr pipe descriptor: %w", err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return stdioPipe, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 01:38:44 +08:00
										 |  |  | func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOptions define.NamespaceOptions, idmapOptions define.IDMappingOptions, policy define.NetworkConfigurationPolicy) (configureNetwork bool, configureNetworks []string, configureUTS bool, err error) { | 
					
						
							| 
									
										
										
										
											2022-09-25 20:00:14 +08:00
										 |  |  | 	defaultContainerConfig, err := config.Default() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false, nil, false, fmt.Errorf("failed to get container config: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	addSysctl := func(prefixes []string) error { | 
					
						
							|  |  |  | 		for _, sysctl := range defaultContainerConfig.Sysctls() { | 
					
						
							|  |  |  | 			splitn := strings.SplitN(sysctl, "=", 2) | 
					
						
							|  |  |  | 			if len(splitn) > 2 { | 
					
						
							|  |  |  | 				return fmt.Errorf("sysctl %q defined in containers.conf must be formatted name=value", sysctl) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			for _, prefix := range prefixes { | 
					
						
							|  |  |  | 				if strings.HasPrefix(splitn[0], prefix) { | 
					
						
							|  |  |  | 					g.AddLinuxSysctl(splitn[0], splitn[1]) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	// Set namespace options in the container configuration.
 | 
					
						
							|  |  |  | 	configureUserns := false | 
					
						
							|  |  |  | 	specifiedNetwork := false | 
					
						
							|  |  |  | 	for _, namespaceOption := range namespaceOptions { | 
					
						
							|  |  |  | 		switch namespaceOption.Name { | 
					
						
							| 
									
										
										
										
											2022-09-25 20:00:14 +08:00
										 |  |  | 		case string(specs.IPCNamespace): | 
					
						
							|  |  |  | 			if !namespaceOption.Host { | 
					
						
							|  |  |  | 				if err := addSysctl([]string{"fs.mqueue"}); err != nil { | 
					
						
							|  |  |  | 					return false, nil, false, err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		case string(specs.UserNamespace): | 
					
						
							|  |  |  | 			configureUserns = false | 
					
						
							|  |  |  | 			if !namespaceOption.Host && namespaceOption.Path == "" { | 
					
						
							|  |  |  | 				configureUserns = true | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case string(specs.NetworkNamespace): | 
					
						
							|  |  |  | 			specifiedNetwork = true | 
					
						
							|  |  |  | 			configureNetwork = false | 
					
						
							|  |  |  | 			if !namespaceOption.Host && (namespaceOption.Path == "" || !filepath.IsAbs(namespaceOption.Path)) { | 
					
						
							|  |  |  | 				if namespaceOption.Path != "" && !filepath.IsAbs(namespaceOption.Path) { | 
					
						
							|  |  |  | 					configureNetworks = strings.Split(namespaceOption.Path, ",") | 
					
						
							|  |  |  | 					namespaceOption.Path = "" | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2021-02-07 06:49:40 +08:00
										 |  |  | 				configureNetwork = (policy != define.NetworkDisabled) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		case string(specs.UTSNamespace): | 
					
						
							|  |  |  | 			configureUTS = false | 
					
						
							| 
									
										
										
										
											2022-09-25 20:00:14 +08:00
										 |  |  | 			if !namespaceOption.Host { | 
					
						
							|  |  |  | 				if namespaceOption.Path == "" { | 
					
						
							|  |  |  | 					configureUTS = true | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if err := addSysctl([]string{"kernel.hostname", "kernel.domainame"}); err != nil { | 
					
						
							|  |  |  | 					return false, nil, false, err | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if namespaceOption.Host { | 
					
						
							|  |  |  | 			if err := g.RemoveLinuxNamespace(namespaceOption.Name); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 				return false, nil, false, fmt.Errorf("removing %q namespace for run: %w", namespaceOption.Name, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} else if err := g.AddOrReplaceLinuxNamespace(namespaceOption.Name, namespaceOption.Path); err != nil { | 
					
						
							|  |  |  | 			if namespaceOption.Path == "" { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 				return false, nil, false, fmt.Errorf("adding new %q namespace for run: %w", namespaceOption.Name, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return false, nil, false, fmt.Errorf("adding %q namespace %q for run: %w", namespaceOption.Name, namespaceOption.Path, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// If we've got mappings, we're going to have to create a user namespace.
 | 
					
						
							|  |  |  | 	if len(idmapOptions.UIDMap) > 0 || len(idmapOptions.GIDMap) > 0 || configureUserns { | 
					
						
							| 
									
										
										
										
											2019-07-16 22:47:25 +08:00
										 |  |  | 		if err := g.AddOrReplaceLinuxNamespace(string(specs.UserNamespace), ""); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return false, nil, false, fmt.Errorf("adding new %q namespace for run: %w", string(specs.UserNamespace), err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		hostUidmap, hostGidmap, err := unshare.GetHostIDMappings("") | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return false, nil, false, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for _, m := range idmapOptions.UIDMap { | 
					
						
							|  |  |  | 			g.AddLinuxUIDMapping(m.HostID, m.ContainerID, m.Size) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if len(idmapOptions.UIDMap) == 0 { | 
					
						
							|  |  |  | 			for _, m := range hostUidmap { | 
					
						
							|  |  |  | 				g.AddLinuxUIDMapping(m.ContainerID, m.ContainerID, m.Size) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for _, m := range idmapOptions.GIDMap { | 
					
						
							|  |  |  | 			g.AddLinuxGIDMapping(m.HostID, m.ContainerID, m.Size) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if len(idmapOptions.GIDMap) == 0 { | 
					
						
							|  |  |  | 			for _, m := range hostGidmap { | 
					
						
							|  |  |  | 				g.AddLinuxGIDMapping(m.ContainerID, m.ContainerID, m.Size) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if !specifiedNetwork { | 
					
						
							| 
									
										
										
										
											2019-07-16 22:47:25 +08:00
										 |  |  | 			if err := g.AddOrReplaceLinuxNamespace(string(specs.NetworkNamespace), ""); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 				return false, nil, false, fmt.Errorf("adding new %q namespace for run: %w", string(specs.NetworkNamespace), err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2021-02-07 06:49:40 +08:00
										 |  |  | 			configureNetwork = (policy != define.NetworkDisabled) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2019-07-16 22:47:25 +08:00
										 |  |  | 		if err := g.RemoveLinuxNamespace(string(specs.UserNamespace)); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return false, nil, false, fmt.Errorf("removing %q namespace for run: %w", string(specs.UserNamespace), err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if !specifiedNetwork { | 
					
						
							| 
									
										
										
										
											2019-07-16 22:47:25 +08:00
										 |  |  | 			if err := g.RemoveLinuxNamespace(string(specs.NetworkNamespace)); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 				return false, nil, false, fmt.Errorf("removing %q namespace for run: %w", string(specs.NetworkNamespace), err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-09-25 20:00:14 +08:00
										 |  |  | 	if configureNetwork { | 
					
						
							|  |  |  | 		if err := addSysctl([]string{"net"}); err != nil { | 
					
						
							|  |  |  | 			return false, nil, false, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2021-03-02 02:07:58 +08:00
										 |  |  | 		for name, val := range define.DefaultNetworkSysctl { | 
					
						
							| 
									
										
										
										
											2019-05-28 18:25:39 +08:00
										 |  |  | 			// Check that the sysctl we are adding is actually supported
 | 
					
						
							|  |  |  | 			// by the kernel
 | 
					
						
							|  |  |  | 			p := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1)) | 
					
						
							|  |  |  | 			_, err := os.Stat(p) | 
					
						
							| 
									
										
										
										
											2022-07-27 03:27:30 +08:00
										 |  |  | 			if err != nil && !errors.Is(err, os.ErrNotExist) { | 
					
						
							| 
									
										
										
										
											2020-10-15 17:16:50 +08:00
										 |  |  | 				return false, nil, false, err | 
					
						
							| 
									
										
										
										
											2019-05-28 18:25:39 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				g.AddLinuxSysctl(name, val) | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2021-05-08 01:38:44 +08:00
										 |  |  | 				logger.Warnf("ignoring sysctl %s since %s doesn't exist", name, p) | 
					
						
							| 
									
										
										
										
											2019-05-28 18:25:39 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return configureNetwork, configureNetworks, configureUTS, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-27 17:13:35 +08:00
										 |  |  | func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions) (bool, []string, error) { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	defaultNamespaceOptions, err := DefaultNamespaceOptions() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false, nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	namespaceOptions := defaultNamespaceOptions | 
					
						
							|  |  |  | 	namespaceOptions.AddOrReplace(b.NamespaceOptions...) | 
					
						
							|  |  |  | 	namespaceOptions.AddOrReplace(options.NamespaceOptions...) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	networkPolicy := options.ConfigureNetwork | 
					
						
							| 
									
										
										
										
											2022-01-21 19:59:49 +08:00
										 |  |  | 	//Nothing was specified explicitly so network policy should be inherited from builder
 | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	if networkPolicy == NetworkDefault { | 
					
						
							|  |  |  | 		networkPolicy = b.ConfigureNetwork | 
					
						
							| 
									
										
										
										
											2021-10-27 17:13:35 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// If builder policy was NetworkDisabled and
 | 
					
						
							|  |  |  | 		// we want to disable network for this run.
 | 
					
						
							|  |  |  | 		// reset options.ConfigureNetwork to NetworkDisabled
 | 
					
						
							|  |  |  | 		// since it will be treated as source of truth later.
 | 
					
						
							|  |  |  | 		if networkPolicy == NetworkDisabled { | 
					
						
							|  |  |  | 			options.ConfigureNetwork = networkPolicy | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-09-11 20:01:43 +08:00
										 |  |  | 	if networkPolicy == NetworkDisabled { | 
					
						
							|  |  |  | 		namespaceOptions.AddOrReplace(define.NamespaceOptions{{Name: string(specs.NetworkNamespace), Host: false}}...) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-05-08 01:38:44 +08:00
										 |  |  | 	configureNetwork, configureNetworks, configureUTS, err := setupNamespaces(options.Logger, g, namespaceOptions, b.IDMappingOptions, networkPolicy) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return false, nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if configureUTS { | 
					
						
							|  |  |  | 		if options.Hostname != "" { | 
					
						
							|  |  |  | 			g.SetHostname(options.Hostname) | 
					
						
							|  |  |  | 		} else if b.Hostname() != "" { | 
					
						
							|  |  |  | 			g.SetHostname(b.Hostname()) | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			g.SetHostname(stringid.TruncateID(b.ContainerID)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		g.SetHostname("") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	found := false | 
					
						
							|  |  |  | 	spec := g.Config | 
					
						
							|  |  |  | 	for i := range spec.Process.Env { | 
					
						
							|  |  |  | 		if strings.HasPrefix(spec.Process.Env[i], "HOSTNAME=") { | 
					
						
							|  |  |  | 			found = true | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !found { | 
					
						
							|  |  |  | 		spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("HOSTNAME=%s", spec.Hostname)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return configureNetwork, configureNetworks, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-16 16:47:48 +08:00
										 |  |  | func runSetupBoundFiles(bundlePath string, bindFiles map[string]string) (mounts []specs.Mount) { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	for dest, src := range bindFiles { | 
					
						
							|  |  |  | 		options := []string{"rbind"} | 
					
						
							|  |  |  | 		if strings.HasPrefix(src, bundlePath) { | 
					
						
							|  |  |  | 			options = append(options, bind.NoBindOption) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mounts = append(mounts, specs.Mount{ | 
					
						
							|  |  |  | 			Source:      src, | 
					
						
							|  |  |  | 			Destination: dest, | 
					
						
							|  |  |  | 			Type:        "bind", | 
					
						
							|  |  |  | 			Options:     options, | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-16 16:47:48 +08:00
										 |  |  | 	return mounts | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-08 01:54:18 +08:00
										 |  |  | func addRlimits(ulimit []string, g *generate.Generator, defaultUlimits []string) error { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		ul  *units.Ulimit | 
					
						
							|  |  |  | 		err error | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-08 01:54:18 +08:00
										 |  |  | 	ulimit = append(defaultUlimits, ulimit...) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	for _, u := range ulimit { | 
					
						
							|  |  |  | 		if ul, err = units.ParseUlimit(u); err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 			return fmt.Errorf("ulimit option %q requires name=SOFT:HARD, failed to be parsed: %w", u, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		g.AddProcessRlimits("RLIMIT_"+strings.ToUpper(ul.Name), uint64(ul.Hard), uint64(ul.Soft)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-27 10:47:30 +08:00
										 |  |  | func (b *Builder) runSetupVolumeMounts(mountLabel string, volumeMounts []string, optionMounts []specs.Mount, idMaps IDMaps) (mounts []specs.Mount, Err error) { | 
					
						
							| 
									
										
										
										
											2019-05-30 04:34:17 +08:00
										 |  |  | 	// Make sure the overlay directory is clean before running
 | 
					
						
							|  |  |  | 	containerDir, err := b.store.ContainerDirectory(b.ContainerID) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 		return nil, fmt.Errorf("looking up container directory for %s: %w", b.ContainerID, err) | 
					
						
							| 
									
										
										
										
											2019-05-30 04:34:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if err := overlay.CleanupContent(containerDir); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 		return nil, fmt.Errorf("cleaning up overlay content for %s: %w", b.ContainerID, err) | 
					
						
							| 
									
										
										
										
											2019-05-30 04:34:17 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-20 02:17:11 +08:00
										 |  |  | 	parseMount := func(mountType, host, container string, options []string) (specs.Mount, error) { | 
					
						
							| 
									
										
										
										
											2020-11-18 22:50:53 +08:00
										 |  |  | 		var foundrw, foundro, foundz, foundZ, foundO, foundU bool | 
					
						
							| 
									
										
										
										
											2022-01-20 17:15:48 +08:00
										 |  |  | 		var rootProp, upperDir, workDir string | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		for _, opt := range options { | 
					
						
							|  |  |  | 			switch opt { | 
					
						
							|  |  |  | 			case "rw": | 
					
						
							|  |  |  | 				foundrw = true | 
					
						
							|  |  |  | 			case "ro": | 
					
						
							|  |  |  | 				foundro = true | 
					
						
							|  |  |  | 			case "z": | 
					
						
							|  |  |  | 				foundz = true | 
					
						
							|  |  |  | 			case "Z": | 
					
						
							|  |  |  | 				foundZ = true | 
					
						
							| 
									
										
										
										
											2019-04-29 21:41:18 +08:00
										 |  |  | 			case "O": | 
					
						
							|  |  |  | 				foundO = true | 
					
						
							| 
									
										
										
										
											2020-11-18 22:50:53 +08:00
										 |  |  | 			case "U": | 
					
						
							|  |  |  | 				foundU = true | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			case "private", "rprivate", "slave", "rslave", "shared", "rshared": | 
					
						
							|  |  |  | 				rootProp = opt | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-01-20 17:15:48 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			if strings.HasPrefix(opt, "upperdir") { | 
					
						
							|  |  |  | 				splitOpt := strings.SplitN(opt, "=", 2) | 
					
						
							|  |  |  | 				if len(splitOpt) > 1 { | 
					
						
							|  |  |  | 					upperDir = splitOpt[1] | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if strings.HasPrefix(opt, "workdir") { | 
					
						
							|  |  |  | 				splitOpt := strings.SplitN(opt, "=", 2) | 
					
						
							|  |  |  | 				if len(splitOpt) > 1 { | 
					
						
							|  |  |  | 					workDir = splitOpt[1] | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if !foundrw && !foundro { | 
					
						
							|  |  |  | 			options = append(options, "rw") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if foundz { | 
					
						
							|  |  |  | 			if err := label.Relabel(host, mountLabel, true); err != nil { | 
					
						
							| 
									
										
										
										
											2020-10-15 17:16:50 +08:00
										 |  |  | 				return specs.Mount{}, err | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if foundZ { | 
					
						
							|  |  |  | 			if err := label.Relabel(host, mountLabel, false); err != nil { | 
					
						
							| 
									
										
										
										
											2020-10-15 17:16:50 +08:00
										 |  |  | 				return specs.Mount{}, err | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-18 22:50:53 +08:00
										 |  |  | 		if foundU { | 
					
						
							| 
									
										
										
										
											2022-05-27 10:47:30 +08:00
										 |  |  | 			if err := chown.ChangeHostPathOwnership(host, true, idMaps.processUID, idMaps.processGID); err != nil { | 
					
						
							| 
									
										
										
										
											2020-11-18 22:50:53 +08:00
										 |  |  | 				return specs.Mount{}, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-04-29 21:41:18 +08:00
										 |  |  | 		if foundO { | 
					
						
							| 
									
										
										
										
											2022-01-20 17:15:48 +08:00
										 |  |  | 			if (upperDir != "" && workDir == "") || (workDir != "" && upperDir == "") { | 
					
						
							|  |  |  | 				return specs.Mount{}, errors.New("if specifying upperdir then workdir must be specified or vice versa") | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-13 23:12:32 +08:00
										 |  |  | 			containerDir, err := b.store.ContainerDirectory(b.ContainerID) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return specs.Mount{}, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-27 10:47:30 +08:00
										 |  |  | 			contentDir, err := overlay.TempDir(containerDir, idMaps.rootUID, idMaps.rootGID) | 
					
						
							| 
									
										
										
										
											2019-12-13 23:12:32 +08:00
										 |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2022-07-06 17:14:06 +08:00
										 |  |  | 				return specs.Mount{}, fmt.Errorf("failed to create TempDir in the %s directory: %w", containerDir, err) | 
					
						
							| 
									
										
										
										
											2019-12-13 23:12:32 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-07 06:22:49 +08:00
										 |  |  | 			graphOptions := b.store.GraphOptions() | 
					
						
							|  |  |  | 			graphOptsCopy := make([]string, len(graphOptions)) | 
					
						
							|  |  |  | 			copy(graphOptsCopy, graphOptions) | 
					
						
							| 
									
										
										
										
											2022-05-27 10:47:30 +08:00
										 |  |  | 			overlayOpts := overlay.Options{ | 
					
						
							|  |  |  | 				RootUID:                idMaps.rootUID, | 
					
						
							|  |  |  | 				RootGID:                idMaps.rootGID, | 
					
						
							| 
									
										
										
										
											2022-01-20 17:15:48 +08:00
										 |  |  | 				UpperDirOptionFragment: upperDir, | 
					
						
							|  |  |  | 				WorkDirOptionFragment:  workDir, | 
					
						
							| 
									
										
										
										
											2025-02-05 23:52:17 +08:00
										 |  |  | 				// Backport note: Cannot use `GraphOpts: slices.Clone(b.store.GraphOptions()),`
 | 
					
						
							|  |  |  | 				// here because "golang.org/x/exp/slices" requires golang 1.18+ which is not
 | 
					
						
							|  |  |  | 				// compatible with the targets of this release branch.
 | 
					
						
							| 
									
										
										
										
											2024-11-07 06:22:49 +08:00
										 |  |  | 				GraphOpts:              graphOptsCopy, | 
					
						
							| 
									
										
										
										
											2022-01-20 17:15:48 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			overlayMount, err := overlay.MountWithOptions(contentDir, host, container, &overlayOpts) | 
					
						
							| 
									
										
										
										
											2019-04-29 21:41:18 +08:00
										 |  |  | 			if err == nil { | 
					
						
							|  |  |  | 				b.TempVolumes[contentDir] = true | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2020-11-18 22:50:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			// If chown true, add correct ownership to the overlay temp directories.
 | 
					
						
							| 
									
										
										
										
											2024-11-07 06:22:49 +08:00
										 |  |  | 			if err == nil && foundU { | 
					
						
							| 
									
										
										
										
											2022-05-27 10:47:30 +08:00
										 |  |  | 				if err := chown.ChangeHostPathOwnership(contentDir, true, idMaps.processUID, idMaps.processGID); err != nil { | 
					
						
							| 
									
										
										
										
											2020-11-18 22:50:53 +08:00
										 |  |  | 					return specs.Mount{}, err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-29 21:41:18 +08:00
										 |  |  | 			return overlayMount, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		if rootProp == "" { | 
					
						
							|  |  |  | 			options = append(options, "private") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-06-20 02:17:11 +08:00
										 |  |  | 		if mountType != "tmpfs" { | 
					
						
							|  |  |  | 			mountType = "bind" | 
					
						
							|  |  |  | 			options = append(options, "rbind") | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		return specs.Mount{ | 
					
						
							|  |  |  | 			Destination: container, | 
					
						
							| 
									
										
										
										
											2019-06-20 02:17:11 +08:00
										 |  |  | 			Type:        mountType, | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			Source:      host, | 
					
						
							| 
									
										
										
										
											2019-06-20 02:17:11 +08:00
										 |  |  | 			Options:     options, | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-29 21:41:18 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	// Bind mount volumes specified for this particular Run() invocation
 | 
					
						
							|  |  |  | 	for _, i := range optionMounts { | 
					
						
							|  |  |  | 		logrus.Debugf("setting up mounted volume at %q", i.Destination) | 
					
						
							| 
									
										
										
										
											2019-06-20 02:17:11 +08:00
										 |  |  | 		mount, err := parseMount(i.Type, i.Source, i.Destination, i.Options) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mounts = append(mounts, mount) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Bind mount volumes given by the user when the container was created
 | 
					
						
							|  |  |  | 	for _, i := range volumeMounts { | 
					
						
							|  |  |  | 		var options []string | 
					
						
							| 
									
										
										
										
											2021-10-11 11:26:35 +08:00
										 |  |  | 		spliti := parse.SplitStringWithColonEscape(i) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		if len(spliti) > 2 { | 
					
						
							|  |  |  | 			options = strings.Split(spliti[2], ",") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		options = append(options, "rbind") | 
					
						
							| 
									
										
										
										
											2019-06-20 02:17:11 +08:00
										 |  |  | 		mount, err := parseMount("bind", spliti[0], spliti[1], options) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mounts = append(mounts, mount) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return mounts, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func setupMaskedPaths(g *generate.Generator) { | 
					
						
							|  |  |  | 	for _, mp := range []string{ | 
					
						
							|  |  |  | 		"/proc/acpi", | 
					
						
							|  |  |  | 		"/proc/kcore", | 
					
						
							|  |  |  | 		"/proc/keys", | 
					
						
							|  |  |  | 		"/proc/latency_stats", | 
					
						
							|  |  |  | 		"/proc/timer_list", | 
					
						
							|  |  |  | 		"/proc/timer_stats", | 
					
						
							|  |  |  | 		"/proc/sched_debug", | 
					
						
							|  |  |  | 		"/proc/scsi", | 
					
						
							|  |  |  | 		"/sys/firmware", | 
					
						
							| 
									
										
										
										
											2020-07-07 22:00:43 +08:00
										 |  |  | 		"/sys/fs/selinux", | 
					
						
							| 
									
										
										
										
											2020-07-14 04:18:32 +08:00
										 |  |  | 		"/sys/dev", | 
					
						
							| 
									
										
										
										
											2023-10-30 22:37:37 +08:00
										 |  |  | 		"/sys/devices/virtual/powercap", | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} { | 
					
						
							|  |  |  | 		g.AddLinuxMaskedPaths(mp) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func setupReadOnlyPaths(g *generate.Generator) { | 
					
						
							|  |  |  | 	for _, rp := range []string{ | 
					
						
							|  |  |  | 		"/proc/asound", | 
					
						
							|  |  |  | 		"/proc/bus", | 
					
						
							|  |  |  | 		"/proc/fs", | 
					
						
							|  |  |  | 		"/proc/irq", | 
					
						
							|  |  |  | 		"/proc/sys", | 
					
						
							|  |  |  | 		"/proc/sysrq-trigger", | 
					
						
							|  |  |  | 	} { | 
					
						
							|  |  |  | 		g.AddLinuxReadonlyPaths(rp) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func setupCapAdd(g *generate.Generator, caps ...string) error { | 
					
						
							|  |  |  | 	for _, cap := range caps { | 
					
						
							|  |  |  | 		if err := g.AddProcessCapabilityBounding(cap); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return fmt.Errorf("adding %q to the bounding capability set: %w", cap, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if err := g.AddProcessCapabilityEffective(cap); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return fmt.Errorf("adding %q to the effective capability set: %w", cap, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if err := g.AddProcessCapabilityPermitted(cap); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return fmt.Errorf("adding %q to the permitted capability set: %w", cap, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if err := g.AddProcessCapabilityAmbient(cap); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return fmt.Errorf("adding %q to the ambient capability set: %w", cap, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func setupCapDrop(g *generate.Generator, caps ...string) error { | 
					
						
							|  |  |  | 	for _, cap := range caps { | 
					
						
							|  |  |  | 		if err := g.DropProcessCapabilityBounding(cap); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return fmt.Errorf("removing %q from the bounding capability set: %w", cap, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if err := g.DropProcessCapabilityEffective(cap); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return fmt.Errorf("removing %q from the effective capability set: %w", cap, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if err := g.DropProcessCapabilityPermitted(cap); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return fmt.Errorf("removing %q from the permitted capability set: %w", cap, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		if err := g.DropProcessCapabilityAmbient(cap); err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-18 18:36:08 +08:00
										 |  |  | 			return fmt.Errorf("removing %q from the ambient capability set: %w", cap, err) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-14 20:12:56 +08:00
										 |  |  | func setupCapabilities(g *generate.Generator, defaultCapabilities, adds, drops []string) error { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	g.ClearProcessCapabilities() | 
					
						
							| 
									
										
										
										
											2020-01-14 20:12:56 +08:00
										 |  |  | 	if err := setupCapAdd(g, defaultCapabilities...); err != nil { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-14 20:12:56 +08:00
										 |  |  | 	for _, c := range adds { | 
					
						
							|  |  |  | 		if strings.ToLower(c) == "all" { | 
					
						
							| 
									
										
										
										
											2020-02-19 03:50:08 +08:00
										 |  |  | 			adds = capabilities.AllCapabilities() | 
					
						
							| 
									
										
										
										
											2020-01-14 20:12:56 +08:00
										 |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-14 20:12:56 +08:00
										 |  |  | 	for _, c := range drops { | 
					
						
							|  |  |  | 		if strings.ToLower(c) == "all" { | 
					
						
							|  |  |  | 			g.ClearProcessCapabilities() | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-14 20:12:56 +08:00
										 |  |  | 	if err := setupCapAdd(g, adds...); err != nil { | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-01-14 20:12:56 +08:00
										 |  |  | 	return setupCapDrop(g, drops...) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-25 17:51:47 +08:00
										 |  |  | func addOrReplaceMount(mounts []specs.Mount, mount specs.Mount) []spec.Mount { | 
					
						
							|  |  |  | 	for i := range mounts { | 
					
						
							|  |  |  | 		if mounts[i].Destination == mount.Destination { | 
					
						
							|  |  |  | 			mounts[i] = mount | 
					
						
							|  |  |  | 			return mounts | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-05-25 17:51:47 +08:00
										 |  |  | 	return append(mounts, mount) | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | // setupSpecialMountSpecChanges creates special mounts for depending on the namespaces
 | 
					
						
							|  |  |  | // logic taken from podman and adapted for buildah
 | 
					
						
							|  |  |  | // https://github.com/containers/podman/blob/4ba71f955a944790edda6e007e6d074009d437a7/pkg/specgen/generate/oci.go#L178
 | 
					
						
							|  |  |  | func setupSpecialMountSpecChanges(spec *spec.Spec, shmSize string) ([]specs.Mount, error) { | 
					
						
							|  |  |  | 	mounts := spec.Mounts | 
					
						
							|  |  |  | 	isRootless := unshare.IsRootless() | 
					
						
							|  |  |  | 	isNewUserns := false | 
					
						
							|  |  |  | 	isNetns := false | 
					
						
							|  |  |  | 	isPidns := false | 
					
						
							|  |  |  | 	isIpcns := false | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, namespace := range spec.Linux.Namespaces { | 
					
						
							|  |  |  | 		switch namespace.Type { | 
					
						
							|  |  |  | 		case specs.NetworkNamespace: | 
					
						
							|  |  |  | 			isNetns = true | 
					
						
							|  |  |  | 		case specs.UserNamespace: | 
					
						
							|  |  |  | 			isNewUserns = true | 
					
						
							|  |  |  | 		case specs.PIDNamespace: | 
					
						
							|  |  |  | 			isPidns = true | 
					
						
							|  |  |  | 		case specs.IPCNamespace: | 
					
						
							|  |  |  | 			isIpcns = true | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	addCgroup := true | 
					
						
							|  |  |  | 	// mount sys when root and no userns or when both netns and userns are private
 | 
					
						
							|  |  |  | 	canMountSys := (!isRootless && !isNewUserns) || (isNetns && isNewUserns) | 
					
						
							|  |  |  | 	if !canMountSys { | 
					
						
							|  |  |  | 		addCgroup = false | 
					
						
							|  |  |  | 		sys := "/sys" | 
					
						
							|  |  |  | 		sysMnt := specs.Mount{ | 
					
						
							|  |  |  | 			Destination: sys, | 
					
						
							|  |  |  | 			Type:        "bind", | 
					
						
							|  |  |  | 			Source:      sys, | 
					
						
							|  |  |  | 			Options:     []string{bind.NoBindOption, "rprivate", "nosuid", "noexec", "nodev", "ro", "rbind"}, | 
					
						
							| 
									
										
										
										
											2021-11-04 20:45:40 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 		mounts = addOrReplaceMount(mounts, sysMnt) | 
					
						
							| 
									
										
										
										
											2021-11-04 20:45:40 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 	gid5Available := true | 
					
						
							|  |  |  | 	if isRootless { | 
					
						
							|  |  |  | 		_, gids, err := unshare.GetHostIDMappings("") | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		gid5Available = checkIdsGreaterThan5(gids) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if gid5Available && len(spec.Linux.GIDMappings) > 0 { | 
					
						
							|  |  |  | 		gid5Available = checkIdsGreaterThan5(spec.Linux.GIDMappings) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if !gid5Available { | 
					
						
							|  |  |  | 		// If we have no GID mappings, the gid=5 default option would fail, so drop it.
 | 
					
						
							|  |  |  | 		devPts := specs.Mount{ | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			Destination: "/dev/pts", | 
					
						
							|  |  |  | 			Type:        "devpts", | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 			Source:      "devpts", | 
					
						
							|  |  |  | 			Options:     []string{"rprivate", "nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620"}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mounts = addOrReplaceMount(mounts, devPts) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	isUserns := isNewUserns || isRootless | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if isUserns && !isIpcns { | 
					
						
							|  |  |  | 		devMqueue := "/dev/mqueue" | 
					
						
							|  |  |  | 		devMqueueMnt := specs.Mount{ | 
					
						
							|  |  |  | 			Destination: devMqueue, | 
					
						
							|  |  |  | 			Type:        "bind", | 
					
						
							|  |  |  | 			Source:      devMqueue, | 
					
						
							|  |  |  | 			Options:     []string{bind.NoBindOption, "bind", "nosuid", "noexec", "nodev"}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mounts = addOrReplaceMount(mounts, devMqueueMnt) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if isUserns && !isPidns { | 
					
						
							|  |  |  | 		proc := "/proc" | 
					
						
							|  |  |  | 		procMount := specs.Mount{ | 
					
						
							|  |  |  | 			Destination: proc, | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 			Type:        "bind", | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 			Source:      proc, | 
					
						
							|  |  |  | 			Options:     []string{bind.NoBindOption, "rbind", "nosuid", "noexec", "nodev"}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mounts = addOrReplaceMount(mounts, procMount) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-12-02 03:08:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 	if addCgroup { | 
					
						
							|  |  |  | 		cgroupMnt := specs.Mount{ | 
					
						
							|  |  |  | 			Destination: "/sys/fs/cgroup", | 
					
						
							|  |  |  | 			Type:        "cgroup", | 
					
						
							|  |  |  | 			Source:      "cgroup", | 
					
						
							|  |  |  | 			Options:     []string{"rprivate", "nosuid", "noexec", "nodev", "relatime", "rw"}, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		mounts = addOrReplaceMount(mounts, cgroupMnt) | 
					
						
							| 
									
										
										
										
											2021-12-02 03:08:25 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// if userns and host ipc bind mount shm
 | 
					
						
							|  |  |  | 	if isUserns && !isIpcns { | 
					
						
							|  |  |  | 		// bind mount /dev/shm when it exists
 | 
					
						
							|  |  |  | 		if _, err := os.Stat("/dev/shm"); err == nil { | 
					
						
							|  |  |  | 			shmMount := specs.Mount{ | 
					
						
							|  |  |  | 				Source:      "/dev/shm", | 
					
						
							|  |  |  | 				Type:        "bind", | 
					
						
							|  |  |  | 				Destination: "/dev/shm", | 
					
						
							|  |  |  | 				Options:     []string{bind.NoBindOption, "rbind", "nosuid", "noexec", "nodev"}, | 
					
						
							| 
									
										
										
										
											2021-12-02 03:08:25 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 			mounts = addOrReplaceMount(mounts, shmMount) | 
					
						
							| 
									
										
										
										
											2021-12-02 03:08:25 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 	} else if shmSize != "" { | 
					
						
							|  |  |  | 		shmMount := specs.Mount{ | 
					
						
							|  |  |  | 			Source:      "shm", | 
					
						
							|  |  |  | 			Destination: "/dev/shm", | 
					
						
							|  |  |  | 			Type:        "tmpfs", | 
					
						
							|  |  |  | 			Options:     []string{"private", "nodev", "noexec", "nosuid", "mode=1777", "size=" + shmSize}, | 
					
						
							| 
									
										
										
										
											2021-12-02 03:08:25 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 		mounts = addOrReplaceMount(mounts, shmMount) | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return mounts, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func checkIdsGreaterThan5(ids []spec.LinuxIDMapping) bool { | 
					
						
							|  |  |  | 	for _, r := range ids { | 
					
						
							|  |  |  | 		if r.ContainerID <= 5 && 5 < r.ContainerID+r.Size { | 
					
						
							|  |  |  | 			return true | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-04-04 21:58:18 +08:00
										 |  |  | 	return false | 
					
						
							| 
									
										
										
										
											2019-04-26 03:39:49 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-14 05:55:59 +08:00
										 |  |  | // Returns a Mount to add to the runtime spec's list of mounts, an optional
 | 
					
						
							|  |  |  | // path of a mounted filesystem, unmounted, and an optional lock, or an error.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // The caller is expected to, after the command which uses the mount exits,
 | 
					
						
							|  |  |  | // unmount the mounted filesystem (if we provided the path to its mountpoint)
 | 
					
						
							|  |  |  | // and remove its mountpoint, , and release the lock (if we took one).
 | 
					
						
							|  |  |  | func (b *Builder) getCacheMount(tokens []string, stageMountPoints map[string]internal.StageMountDetails, idMaps IDMaps, workDir, tmpDir string) (*spec.Mount, string, *lockfile.LockFile, error) { | 
					
						
							| 
									
										
										
										
											2021-10-07 16:27:17 +08:00
										 |  |  | 	var optionMounts []specs.Mount | 
					
						
							| 
									
										
										
										
											2024-12-14 05:55:59 +08:00
										 |  |  | 	optionMount, intermediateMount, targetLock, err := internalParse.GetCacheMount(tokens, stageMountPoints, workDir, tmpDir) | 
					
						
							| 
									
										
										
										
											2021-10-07 16:27:17 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-12-14 05:55:59 +08:00
										 |  |  | 		return nil, "", nil, err | 
					
						
							| 
									
										
										
										
											2021-10-07 16:27:17 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-19 08:55:01 +08:00
										 |  |  | 	succeeded := false | 
					
						
							|  |  |  | 	defer func() { | 
					
						
							| 
									
										
										
										
											2024-12-14 05:55:59 +08:00
										 |  |  | 		if !succeeded { | 
					
						
							|  |  |  | 			if intermediateMount != "" { | 
					
						
							|  |  |  | 				if err := mount.Unmount(intermediateMount); err != nil { | 
					
						
							|  |  |  | 					b.Logger.Debugf("ummounting %q: %v", intermediateMount, err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				if err := os.Remove(intermediateMount); err != nil { | 
					
						
							|  |  |  | 					b.Logger.Debugf("removing should-be-empty directory %q: %v", intermediateMount, err) | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if targetLock != nil { | 
					
						
							|  |  |  | 				targetLock.Unlock() | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2022-10-19 08:55:01 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2024-12-14 05:55:59 +08:00
										 |  |  | 	optionMounts = append(optionMounts, optionMount) | 
					
						
							| 
									
										
										
										
											2022-05-27 10:47:30 +08:00
										 |  |  | 	volumes, err := b.runSetupVolumeMounts(b.MountLabel, nil, optionMounts, idMaps) | 
					
						
							| 
									
										
										
										
											2021-10-07 16:27:17 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2024-12-14 05:55:59 +08:00
										 |  |  | 		return nil, "", nil, err | 
					
						
							| 
									
										
										
										
											2021-10-07 16:27:17 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-19 08:55:01 +08:00
										 |  |  | 	succeeded = true | 
					
						
							| 
									
										
										
										
											2024-12-14 05:55:59 +08:00
										 |  |  | 	return &volumes[0], intermediateMount, targetLock, nil | 
					
						
							| 
									
										
										
										
											2021-10-07 16:27:17 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-18 05:33:50 +08:00
										 |  |  | // setPdeathsig sets a parent-death signal for the process
 | 
					
						
							|  |  |  | func setPdeathsig(cmd *exec.Cmd) { | 
					
						
							|  |  |  | 	if cmd.SysProcAttr == nil { | 
					
						
							|  |  |  | 		cmd.SysProcAttr = &syscall.SysProcAttr{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL | 
					
						
							|  |  |  | } |