summaryrefslogtreecommitdiff
path: root/pkg/rootless
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/rootless')
-rw-r--r--pkg/rootless/rootless.go104
-rw-r--r--pkg/rootless/rootless_linux.go117
-rw-r--r--pkg/rootless/rootless_unsupported.go18
3 files changed, 136 insertions, 103 deletions
diff --git a/pkg/rootless/rootless.go b/pkg/rootless/rootless.go
index 737fc91c7..ca851f9bc 100644
--- a/pkg/rootless/rootless.go
+++ b/pkg/rootless/rootless.go
@@ -2,16 +2,9 @@ package rootless
import (
"fmt"
- "io/ioutil"
+ "github.com/containers/storage/pkg/idtools"
"os"
"os/exec"
- gosignal "os/signal"
- "runtime"
- "syscall"
-
- "github.com/containers/storage/pkg/idtools"
- "github.com/docker/docker/pkg/signal"
- "github.com/pkg/errors"
)
/*
@@ -25,11 +18,6 @@ func runInUser() error {
return nil
}
-// IsRootless tells us if we are running in rootless mode
-func IsRootless() bool {
- return os.Getuid() != 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != ""
-}
-
func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap) error {
path, err := exec.LookPath(tool)
if err != nil {
@@ -53,93 +41,3 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
}
return cmd.Run()
}
-
-// BecomeRootInUserNS re-exec podman in a new userNS
-func BecomeRootInUserNS() (bool, error) {
-
- if os.Getuid() == 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" {
- if os.Getenv("_LIBPOD_USERNS_CONFIGURED") == "init" {
- return false, runInUser()
- }
- return false, nil
- }
-
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
-
- r, w, err := os.Pipe()
- if err != nil {
- return false, err
- }
- defer r.Close()
- defer w.Close()
-
- pidC := C.reexec_in_user_namespace(C.int(r.Fd()))
- pid := int(pidC)
- if pid < 0 {
- return false, errors.Errorf("cannot re-exec process")
- }
-
- setgroups := fmt.Sprintf("/proc/%d/setgroups", pid)
- err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666)
- if err != nil {
- return false, errors.Wrapf(err, "cannot write setgroups file")
- }
-
- var uids, gids []idtools.IDMap
- username := os.Getenv("USER")
- mappings, err := idtools.NewIDMappings(username, username)
- if err == nil {
- uids = mappings.UIDs()
- gids = mappings.GIDs()
- }
-
- uidsMapped := false
- if mappings != nil && uids != nil {
- uidsMapped = tryMappingTool("newuidmap", pid, os.Getuid(), uids) == nil
- }
- if !uidsMapped {
- uidMap := fmt.Sprintf("/proc/%d/uid_map", pid)
- err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getuid())), 0666)
- if err != nil {
- return false, errors.Wrapf(err, "cannot write uid_map")
- }
- }
-
- gidsMapped := false
- if mappings != nil && gids != nil {
- gidsMapped = tryMappingTool("newgidmap", pid, os.Getgid(), gids) == nil
- }
- if !gidsMapped {
- gidMap := fmt.Sprintf("/proc/%d/gid_map", pid)
- err = ioutil.WriteFile(gidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getgid())), 0666)
- if err != nil {
- return false, errors.Wrapf(err, "cannot write gid_map")
- }
- }
-
- _, err = w.Write([]byte("1"))
- if err != nil {
- return false, errors.Wrapf(err, "write to sync pipe")
- }
-
- c := make(chan os.Signal, 1)
-
- gosignal.Notify(c)
- defer gosignal.Reset()
- go func() {
- for s := range c {
- if s == signal.SIGCHLD || s == signal.SIGPIPE {
- continue
- }
-
- syscall.Kill(int(pidC), s.(syscall.Signal))
- }
- }()
-
- if C.reexec_in_user_namespace_wait(pidC) < 0 {
- return false, errors.Wrapf(err, "error waiting for the re-exec process")
- }
-
- return true, nil
-}
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
new file mode 100644
index 000000000..5b4094bf2
--- /dev/null
+++ b/pkg/rootless/rootless_linux.go
@@ -0,0 +1,117 @@
+// build +linux
+
+package rootless
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ gosignal "os/signal"
+ "runtime"
+ "syscall"
+
+ "github.com/containers/storage/pkg/idtools"
+ "github.com/docker/docker/pkg/signal"
+ "github.com/pkg/errors"
+)
+
+/*
+extern int reexec_in_user_namespace(int ready);
+extern int reexec_in_user_namespace_wait(int pid);
+*/
+import "C"
+
+// IsRootless tells us if we are running in rootless mode
+func IsRootless() bool {
+ return os.Getuid() != 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != ""
+}
+
+// BecomeRootInUserNS re-exec podman in a new userNS
+func BecomeRootInUserNS() (bool, error) {
+
+ if os.Getuid() == 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" {
+ if os.Getenv("_LIBPOD_USERNS_CONFIGURED") == "init" {
+ return false, runInUser()
+ }
+ return false, nil
+ }
+
+ runtime.LockOSThread()
+ defer runtime.UnlockOSThread()
+
+ r, w, err := os.Pipe()
+ if err != nil {
+ return false, err
+ }
+ defer r.Close()
+ defer w.Close()
+
+ pidC := C.reexec_in_user_namespace(C.int(r.Fd()))
+ pid := int(pidC)
+ if pid < 0 {
+ return false, errors.Errorf("cannot re-exec process")
+ }
+
+ setgroups := fmt.Sprintf("/proc/%d/setgroups", pid)
+ err = ioutil.WriteFile(setgroups, []byte("deny\n"), 0666)
+ if err != nil {
+ return false, errors.Wrapf(err, "cannot write setgroups file")
+ }
+
+ var uids, gids []idtools.IDMap
+ username := os.Getenv("USER")
+ mappings, err := idtools.NewIDMappings(username, username)
+ if err == nil {
+ uids = mappings.UIDs()
+ gids = mappings.GIDs()
+ }
+
+ uidsMapped := false
+ if mappings != nil && uids != nil {
+ uidsMapped = tryMappingTool("newuidmap", pid, os.Getuid(), uids) == nil
+ }
+ if !uidsMapped {
+ uidMap := fmt.Sprintf("/proc/%d/uid_map", pid)
+ err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getuid())), 0666)
+ if err != nil {
+ return false, errors.Wrapf(err, "cannot write uid_map")
+ }
+ }
+
+ gidsMapped := false
+ if mappings != nil && gids != nil {
+ gidsMapped = tryMappingTool("newgidmap", pid, os.Getgid(), gids) == nil
+ }
+ if !gidsMapped {
+ gidMap := fmt.Sprintf("/proc/%d/gid_map", pid)
+ err = ioutil.WriteFile(gidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getgid())), 0666)
+ if err != nil {
+ return false, errors.Wrapf(err, "cannot write gid_map")
+ }
+ }
+
+ _, err = w.Write([]byte("1"))
+ if err != nil {
+ return false, errors.Wrapf(err, "write to sync pipe")
+ }
+
+ c := make(chan os.Signal, 1)
+
+ gosignal.Notify(c)
+ defer gosignal.Reset()
+ go func() {
+ for s := range c {
+ if s == signal.SIGCHLD || s == signal.SIGPIPE {
+ continue
+ }
+
+ syscall.Kill(int(pidC), s.(syscall.Signal))
+ }
+ }()
+
+ if C.reexec_in_user_namespace_wait(pidC) < 0 {
+ return false, errors.Wrapf(err, "error waiting for the re-exec process")
+ }
+
+ return true, nil
+}
diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go
new file mode 100644
index 000000000..e4067a764
--- /dev/null
+++ b/pkg/rootless/rootless_unsupported.go
@@ -0,0 +1,18 @@
+// +build !linux
+
+package rootless
+
+import (
+ "github.com/pkg/errors"
+)
+
+// IsRootless returns false on all non-linux platforms
+func IsRootless() bool {
+ return false
+}
+
+// BecomeRootInUserNS is a stub function that always returns false and an
+// error on unsupported OS's
+func BecomeRootInUserNS() (bool, error) {
+ return false, errors.New("this function is not supported on this os")
+}