From af53724ba6633bcea3be97aac40048991e05284f Mon Sep 17 00:00:00 2001 From: Rune Morling Date: Wed, 28 Aug 2024 17:46:22 +0200 Subject: [PATCH 1/4] manager: Make namespace functions noops This is intended to support solbuild being run with rootlesskit in a user namespace (instead of solbuild itself handling namespaces). Signed-off-by: Rune Morling --- builder/namespaces.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/builder/namespaces.go b/builder/namespaces.go index 3ab209b..435c421 100644 --- a/builder/namespaces.go +++ b/builder/namespaces.go @@ -26,9 +26,9 @@ import ( 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 } From 78f18edb44f4cd554605259aa22bb97acfcfbfab Mon Sep 17 00:00:00 2001 From: Rune Morling Date: Wed, 28 Aug 2024 17:49:57 +0200 Subject: [PATCH 2/4] build: Use rootlesskit instead of fatfakeroot Signed-off-by: Rune Morling --- builder/build.go | 4 +++- builder/namespaces.go | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/builder/build.go b/builder/build.go index 92d426f..c4ab703 100644 --- a/builder/build.go +++ b/builder/build.go @@ -326,7 +326,9 @@ 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 + cmd := fmt.Sprintf("/bin/su %s -- rootlesskit ypkg-build -D %s %s", BuildUser, wdir, ymlFile) if DisableColors { cmd += " -n" } diff --git a/builder/namespaces.go b/builder/namespaces.go index 435c421..bffc056 100644 --- a/builder/namespaces.go +++ b/builder/namespaces.go @@ -17,9 +17,9 @@ package builder import ( - "fmt" + //"fmt" "log/slog" - "syscall" + //"syscall" ) // ConfigureNamespace will unshare() context, entering a new namespace. From 55ee9ff9d7cb5b4a72e4184810faea5a16bfff78 Mon Sep 17 00:00:00 2001 From: Rune Morling Date: Thu, 29 Aug 2024 00:19:02 +0200 Subject: [PATCH 3/4] util+build: Add and use RootlesskitExec function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit assumes the a priori existence of the solbuild user/group on the host system and assumes that this user has been set up with subuids and subgids. Building still fails, but now it fails on su authentication in the inner rootlesskit-owned chroot: ``` [BuildDep] Checking build-deps for lzip-1.24-7 [BuildDep] All build deps satisfied ✓  Now starting build package=lzip ✓  Build command="/bin/su build --command='ypkg-build -D /home/build/work /home/build/work/package.yml'" ✓  RootlesskitExec command="/bin/su solbuild -c rootlesskit chroot /var/cache/solbuild/unstable-x86_64/lzip/union /bin/su build --command='ypkg-build -D /home/build/work /home/build/work/package.yml'" su: Authentication service cannot retrieve authentication info [rootlesskit:child ] error: command [chroot /var/cache/solbuild/unstable-x86_64/lzip/union /bin/su build --command=ypkg-build -D /home/build/work /home/build/work/package.yml] exited: exit status 1 [rootlesskit:parent] error: child exited: exit status 1 ✗  Failed to build packages err="Failed to start build of package, reason: exit status 1\n" ``` ... rather than on failing on attempting to even _invoke_ rootlesskit. Signed-off-by: Rune Morling --- builder/build.go | 18 ++++++++++++++---- builder/util.go | 24 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/builder/build.go b/builder/build.go index c4ab703..e534dee 100644 --- a/builder/build.go +++ b/builder/build.go @@ -328,23 +328,33 @@ func (p *Package) BuildYpkg(notif PidNotifier, usr *UserInfo, pman *EopkgManager // Now build the package // cmd := fmt.Sprintf("/bin/su %s -- fakeroot ypkg-build -D %s %s", BuildUser, wdir, ymlFile) // use rootlesskit instead of fatfakeroot - cmd := fmt.Sprintf("/bin/su %s -- rootlesskit ypkg-build -D %s %s", BuildUser, wdir, ymlFile) + 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", suCmd) - if err := ChrootExec(notif, overlay.MountPoint, cmd); err != nil { + if err := RootlesskitExec(notif, overlay.MountPoint, suCmd); err != nil { return fmt.Errorf("Failed to start build of package, reason: %w\n", err) } diff --git a/builder/util.go b/builder/util.go index 5577885..d869c0f 100644 --- a/builder/util.go +++ b/builder/util.go @@ -208,6 +208,30 @@ 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 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 { From 28a59401ae605abf5c0e7b4936eb333357826484 Mon Sep 17 00:00:00 2001 From: Rune Morling Date: Thu, 29 Aug 2024 09:02:49 +0200 Subject: [PATCH 4/4] build: Might as well try building as "root" Keeping in mind that rootlesskit runs as the host 'solbuild' user, this seems as good as anything; do note that this means that there will be host permission issues that probably need fixing. This commit is for @joebonrichie to work off of Signed-off-by: Rune Morling --- builder/build.go | 6 +++--- builder/util.go | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/builder/build.go b/builder/build.go index e534dee..1f3f3be 100644 --- a/builder/build.go +++ b/builder/build.go @@ -338,7 +338,7 @@ func (p *Package) BuildYpkg(notif PidNotifier, usr *UserInfo, pman *EopkgManager } // need to properly quote the innner -c 'command' syntax - suCmd := fmt.Sprintf("strace /bin/su %s --command='%s'", BuildUser, buildCmd) + //suCmd := fmt.Sprintf("strace /bin/su %s --command='%s'", BuildUser, buildCmd) if p.CanCCache { // Start an sccache server to work around #87 @@ -352,9 +352,9 @@ func (p *Package) BuildYpkg(notif PidNotifier, usr *UserInfo, pman *EopkgManager } slog.Info("Now starting build", "package", p.Name) - slog.Info("Build", "command", suCmd) + slog.Info("Build", "command", buildCmd) - if err := RootlesskitExec(notif, overlay.MountPoint, suCmd); 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/util.go b/builder/util.go index d869c0f..a6404b0 100644 --- a/builder/util.go +++ b/builder/util.go @@ -212,7 +212,8 @@ func ChrootExec(notif PidNotifier, dir, command string) error { // 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 chroot %s %s", dir, command) + 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