From 0ba161dec97c49d8371a21dae9ed8667405baae2 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 10 Mar 2025 10:30:43 +0900 Subject: [PATCH 1/3] Revert "detach-netns: simplify unshare helper" This reverts commit 0dfe464daa35d7bfcfe28684b2a31acfd88a0a9f. Signed-off-by: Akihiro Suda --- cmd/rootlesskit/main.go | 9 +++++ cmd/rootlesskit/unshare/unshare.go | 53 ++++++++++++++++++++++++++++++ pkg/child/child.go | 18 ++++++---- 3 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 cmd/rootlesskit/unshare/unshare.go diff --git a/cmd/rootlesskit/main.go b/cmd/rootlesskit/main.go index c1e060f7..e0bd133c 100644 --- a/cmd/rootlesskit/main.go +++ b/cmd/rootlesskit/main.go @@ -15,6 +15,7 @@ import ( "github.com/sirupsen/logrus" "github.com/urfave/cli/v2" + "github.com/rootless-containers/rootlesskit/v2/cmd/rootlesskit/unshare" "github.com/rootless-containers/rootlesskit/v2/pkg/child" "github.com/rootless-containers/rootlesskit/v2/pkg/common" "github.com/rootless-containers/rootlesskit/v2/pkg/copyup/tmpfssymlink" @@ -41,6 +42,10 @@ const ( ) func main() { + if checkUnshareHelper() { + unshare.Main() + return + } iAmActivationHelper := checkActivationHelper() iAmChild := os.Getenv(pipeFDEnvKey) != "" id := "parent" @@ -701,3 +706,7 @@ func createActivationOpts(clicontext *cli.Context) (activation.Opt, error) { } return opt, nil } + +func checkUnshareHelper() bool { + return filepath.Base(os.Args[0]) == "unshare" +} diff --git a/cmd/rootlesskit/unshare/unshare.go b/cmd/rootlesskit/unshare/unshare.go new file mode 100644 index 00000000..1db6c83a --- /dev/null +++ b/cmd/rootlesskit/unshare/unshare.go @@ -0,0 +1,53 @@ +package unshare + +import ( + "errors" + "fmt" + "os" + "os/exec" + "syscall" + + "github.com/rootless-containers/rootlesskit/v2/pkg/common" + "github.com/rootless-containers/rootlesskit/v2/pkg/version" + "github.com/urfave/cli/v2" +) + +func Main() { + app := cli.NewApp() + app.Name = "unshare" + app.HideHelpCommand = true + app.Version = version.Version + app.Usage = "Reimplementation of unshare(1)" + app.UsageText = "unshare [global options] [arguments...]" + app.Flags = append(app.Flags, &cli.BoolFlag{ + Name: "n,net", + Usage: "unshare network namespace", + }) + app.Action = action + if err := app.Run(os.Args); err != nil { + fmt.Fprintf(os.Stderr, "[rootlesskit:unshare] error: %v\n", err) + // propagate the exit code + code, ok := common.GetExecExitStatus(err) + if !ok { + code = 1 + } + os.Exit(code) + } +} + +func action(clicontext *cli.Context) error { + ctx := clicontext.Context + if clicontext.NArg() < 1 { + return errors.New("no command specified") + } + cmdFlags := clicontext.Args().Slice() + cmd := exec.CommandContext(ctx, cmdFlags[0], cmdFlags[1:]...) + cmd.Stdin = os.Stdin + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.SysProcAttr = &syscall.SysProcAttr{} + if clicontext.Bool("n") { + cmd.SysProcAttr.Cloneflags |= syscall.CLONE_NEWNET + } + return cmd.Run() +} diff --git a/pkg/child/child.go b/pkg/child/child.go index a7440c41..d32cb675 100644 --- a/pkg/child/child.go +++ b/pkg/child/child.go @@ -583,13 +583,19 @@ func NewNetNsWithPathWithoutEnter(p string) error { if err := os.WriteFile(p, nil, 0400); err != nil { return err } - tempNS, err := ns.TempNetNS() + selfExe, err := os.Executable() if err != nil { return err } - defer tempNS.Close() - tempNSPath := tempNS.Path() - return ns.WithNetNSPath(tempNSPath, func(_ ns.NetNS) error { - return unix.Mount(tempNSPath, p, "", unix.MS_BIND, "") - }) + // this is hard (not impossible though) to reimplement in Go: https://github.com/cloudflare/slirpnetstack/commit/d7766a8a77f0093d3cb7a94bd0ccbe3f67d411ba + cmd := exec.Command("unshare", "-n", "mount", "--bind", "/proc/self/ns/net", p) + // Use our own implementation of unshare that is embedded in RootlessKit, so as to + // avoid /etc/apparmor.d/unshare-userns-restrict on Ubuntu 25.04. + // https://github.com/rootless-containers/rootlesskit/issues/494 + cmd.Path = selfExe + out, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("failed to execute %v: %w (out=%q)", cmd.Args, err, string(out)) + } + return nil } From 59a459df858d39ad5f4eafa305545907bf0c48ab Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 10 Mar 2025 10:52:05 +0900 Subject: [PATCH 2/3] v2.3.4 Signed-off-by: Akihiro Suda --- pkg/version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/version.go b/pkg/version/version.go index bfc6d0b8..3fa6b5e0 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -1,3 +1,3 @@ package version -const Version = "2.3.3+dev" +const Version = "2.3.4" From c4026e3ae0ad4767872a873db0433e838348c83e Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Mon, 10 Mar 2025 10:52:15 +0900 Subject: [PATCH 3/3] v2.3.4+dev Signed-off-by: Akihiro Suda --- pkg/version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/version.go b/pkg/version/version.go index 3fa6b5e0..2fdb0cd9 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -1,3 +1,3 @@ package version -const Version = "2.3.4" +const Version = "2.3.4+dev"