summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/rootless/rootless_linux.c32
-rw-r--r--pkg/rootless/rootless_linux.go29
-rw-r--r--pkg/rootless/rootless_unsupported.go6
3 files changed, 65 insertions, 2 deletions
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c
index 1b98f76eb..e894328ce 100644
--- a/pkg/rootless/rootless_linux.c
+++ b/pkg/rootless/rootless_linux.c
@@ -83,7 +83,37 @@ get_cmd_line_args (pid_t pid)
}
int
-reexec_in_user_namespace(int ready)
+reexec_userns_join (int userns)
+{
+ pid_t ppid = getpid ();
+ char uid[16];
+ char **argv;
+ int pid;
+
+ sprintf (uid, "%d", geteuid ());
+
+ argv = get_cmd_line_args (ppid);
+ if (argv == NULL)
+ _exit (EXIT_FAILURE);
+
+ pid = fork ();
+ if (pid)
+ return pid;
+
+ setenv ("_LIBPOD_USERNS_CONFIGURED", "init", 1);
+ setenv ("_LIBPOD_ROOTLESS_UID", uid, 1);
+
+ if (setns (userns, 0) < 0)
+ _exit (EXIT_FAILURE);
+ close (userns);
+
+ execvp (argv[0], argv);
+
+ _exit (EXIT_FAILURE);
+}
+
+int
+reexec_in_user_namespace (int ready)
{
int ret;
pid_t pid;
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 904d22ee2..e218dede0 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -23,6 +23,7 @@ import (
/*
extern int reexec_in_user_namespace(int ready);
extern int reexec_in_user_namespace_wait(int pid);
+extern int reexec_userns_join(int userns);
*/
import "C"
@@ -84,6 +85,32 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
return cmd.Run()
}
+// JoinNS re-exec podman in a new userNS and join the user namespace of the specified
+// PID.
+func JoinNS(pid uint) (bool, int, error) {
+ if os.Getuid() == 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" {
+ return false, -1, nil
+ }
+
+ userNS, err := GetUserNSForPid(pid)
+ if err != nil {
+ return false, -1, err
+ }
+ defer userNS.Close()
+
+ pidC := C.reexec_userns_join(C.int(userNS.Fd()))
+ if int(pidC) < 0 {
+ return false, -1, errors.Errorf("cannot re-exec process")
+ }
+
+ ret := C.reexec_in_user_namespace_wait(pidC)
+ if ret < 0 {
+ return false, -1, errors.New("error waiting for the re-exec process")
+ }
+
+ return true, int(ret), nil
+}
+
// BecomeRootInUserNS re-exec podman in a new userNS. It returns whether podman was re-executed
// into a new user namespace and the return code from the re-executed podman process.
// If podman was re-executed the caller needs to propagate the error code returned by the child
@@ -183,7 +210,7 @@ func BecomeRootInUserNS() (bool, int, error) {
ret := C.reexec_in_user_namespace_wait(pidC)
if ret < 0 {
- return false, -1, errors.Wrapf(err, "error waiting for the re-exec process")
+ return false, -1, errors.New("error waiting for the re-exec process")
}
return true, int(ret), nil
diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go
index 93b04adfd..e0adb3453 100644
--- a/pkg/rootless/rootless_unsupported.go
+++ b/pkg/rootless/rootless_unsupported.go
@@ -33,6 +33,12 @@ func SkipStorageSetup() bool {
return false
}
+// JoinNS re-exec podman in a new userNS and join the user namespace of the specified
+// PID.
+func JoinNS(pid uint) (bool, int, error) {
+ return false, -1, errors.New("this function is not supported on this os")
+}
+
// GetUserNSForPid returns an open FD for the first direct child user namespace that created the process
func GetUserNSForPid(pid uint) (*os.File, error) {
return nil, errors.New("this function is not supported on this os")