diff --git a/builder/build.go b/builder/build.go index 92d426f..1f3f3be 100644 --- a/builder/build.go +++ b/builder/build.go @@ -326,23 +326,35 @@ func (p *Package) BuildYpkg(notif PidNotifier, usr *UserInfo, pman *EopkgManager ymlFile := filepath.Join(wdir, filepath.Base(p.Path)) // Now build the package - cmd := fmt.Sprintf("/bin/su %s -- fakeroot ypkg-build -D %s %s", BuildUser, wdir, ymlFile) + // cmd := fmt.Sprintf("/bin/su %s -- fakeroot ypkg-build -D %s %s", BuildUser, wdir, ymlFile) + // use rootlesskit instead of fatfakeroot + buildCmd := fmt.Sprintf("ypkg-build -D %s %s", wdir, ymlFile) if DisableColors { - cmd += " -n" + buildCmd += " -n" } // Pass unix timestamp of last git update if h != nil && len(h.Updates) > 0 { - cmd += fmt.Sprintf(" -t %v", h.GetLastVersionTimestamp()) + buildCmd += fmt.Sprintf(" -t %v", h.GetLastVersionTimestamp()) } + // need to properly quote the innner -c 'command' syntax + //suCmd := fmt.Sprintf("strace /bin/su %s --command='%s'", BuildUser, buildCmd) + if p.CanCCache { // Start an sccache server to work around #87 StartSccache(overlay.MountPoint) } + // ensure that the BuildUser has /etc/sub{g,u}id files present for use with rootlesskit user namespaces + usermodCmd := fmt.Sprintf("touch /etc/sub{g,u}id && usermod --add-subuids 100000-165535 --add-subgids 100000-165535 %s", BuildUser) + if err := ChrootExec(notif, overlay.MountPoint, usermodCmd); err != nil { + slog.Error(fmt.Sprintf("Failed to ensure that user '%s' has /etc/sub{g,u}id files in chroot", BuildUser)) + } + slog.Info("Now starting build", "package", p.Name) + slog.Info("Build", "command", buildCmd) - if err := ChrootExec(notif, overlay.MountPoint, cmd); err != nil { + if err := RootlesskitExec(notif, overlay.MountPoint, buildCmd); err != nil { return fmt.Errorf("Failed to start build of package, reason: %w\n", err) } diff --git a/builder/namespaces.go b/builder/namespaces.go index 3ab209b..bffc056 100644 --- a/builder/namespaces.go +++ b/builder/namespaces.go @@ -17,18 +17,18 @@ package builder import ( - "fmt" + //"fmt" "log/slog" - "syscall" + //"syscall" ) // ConfigureNamespace will unshare() context, entering a new namespace. func ConfigureNamespace() error { slog.Debug("Configuring container namespace") - if err := syscall.Unshare(syscall.CLONE_NEWNS | syscall.CLONE_NEWIPC); err != nil { - return fmt.Errorf("Failed to configure namespace, reason: %w\n", err) - } + // if err := syscall.Unshare(syscall.CLONE_NEWNS | syscall.CLONE_NEWIPC); err != nil { + // return fmt.Errorf("Failed to configure namespace, reason: %w\n", err) + // } return nil } @@ -37,9 +37,9 @@ func ConfigureNamespace() error { func DropNetworking() error { slog.Debug("Dropping container networking") - if err := syscall.Unshare(syscall.CLONE_NEWNET | syscall.CLONE_NEWUTS); err != nil { - return fmt.Errorf("Failed to drop networking capabilities, reason: %w\n", err) - } + // if err := syscall.Unshare(syscall.CLONE_NEWNET | syscall.CLONE_NEWUTS); err != nil { + // return fmt.Errorf("Failed to drop networking capabilities, reason: %w\n", err) + // } return nil } diff --git a/builder/util.go b/builder/util.go index 5577885..a6404b0 100644 --- a/builder/util.go +++ b/builder/util.go @@ -208,6 +208,31 @@ func ChrootExec(notif PidNotifier, dir, command string) error { return c.Wait() } +// RootlesskitExec is a simple wrapper to return a correctly set up rootlesskit chroot command +// using the 'solbuild' user (expected to exist a priori and have /etc/sub{g,u}id files), +// such that we can store the PID for long running tasks. +func RootlesskitExec(notif PidNotifier, dir, command string) error { + rootlesskitCmd := fmt.Sprintf( + "-c rootlesskit --copy-up=/var/cache/eopkg/archives chroot %s %s", dir, command) + args := []string{"solbuild", rootlesskitCmd} + c := exec.Command("/bin/su", args...) + c.Stdout = os.Stdout + c.Stderr = os.Stdout + c.Stdin = os.Stdin + c.Env = ChrootEnvironment + c.SysProcAttr = &syscall.SysProcAttr{Setsid: true} + + slog.Info("RootlesskitExec", "command", c) + + if err := c.Start(); err != nil { + return err + } + + notif.SetActivePID(c.Process.Pid) + + return c.Wait() +} + // ChrootExecStdin is almost identical to ChrootExec, except it permits a stdin // to be associated with the command. func ChrootExecStdin(notif PidNotifier, dir, command string) error {