summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivan@redhat.com>2019-03-10 11:22:57 +0100
committerGiuseppe Scrivano <gscrivan@redhat.com>2019-03-11 11:48:25 +0100
commitf31ba2929ba64f5f279bb3d8d60562d4b77fd0df (patch)
treeac2a0087eae5269ce861a36786bcab35b110ae28
parente22fc79f39a974323cb9463996accacb864e4284 (diff)
downloadpodman-f31ba2929ba64f5f279bb3d8d60562d4b77fd0df.tar.gz
podman-f31ba2929ba64f5f279bb3d8d60562d4b77fd0df.tar.bz2
podman-f31ba2929ba64f5f279bb3d8d60562d4b77fd0df.zip
rootless: support a custom arg to the new process
let the process running as euid != 0 pass down an argument to the process running in the user namespace. This will be useful for commands like rm -a that needs to join different namespaces, so that we can re-exec separately for each of them. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
-rw-r--r--pkg/rootless/rootless.go9
-rw-r--r--pkg/rootless/rootless_linux.go37
-rw-r--r--pkg/rootless/rootless_unsupported.go33
3 files changed, 71 insertions, 8 deletions
diff --git a/pkg/rootless/rootless.go b/pkg/rootless/rootless.go
new file mode 100644
index 000000000..a531e43ce
--- /dev/null
+++ b/pkg/rootless/rootless.go
@@ -0,0 +1,9 @@
+package rootless
+
+// Opts allows to customize how re-execing to a rootless process is done
+type Opts struct {
+ // Argument overrides the arguments on the command line
+ // for the re-execed process. The process in the namespace
+ // must use rootless.Argument() to read its value.
+ Argument string
+}
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 933cfa2c2..69614cefc 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -61,6 +61,11 @@ func SkipStorageSetup() bool {
return skipStorageSetup
}
+// Argument returns the argument that was set for the rootless session.
+func Argument() string {
+ return os.Getenv("_LIBPOD_ROOTLESS_ARG")
+}
+
// GetRootlessUID returns the UID of the user in the parent userNS
func GetRootlessUID() int {
uidEnv := os.Getenv("_LIBPOD_ROOTLESS_UID")
@@ -135,8 +140,16 @@ func JoinNS(pid uint, preserveFDs int) (bool, int, error) {
// JoinDirectUserAndMountNS re-exec podman in a new userNS and join the user and mount
// namespace of the specified PID without looking up its parent. Useful to join directly
-// the conmon process.
+// the conmon process. It is a convenience function for JoinDirectUserAndMountNSWithOpts
+// with a default configuration.
func JoinDirectUserAndMountNS(pid uint) (bool, int, error) {
+ return JoinDirectUserAndMountNSWithOpts(pid, nil)
+}
+
+// JoinDirectUserAndMountNSWithOpts re-exec podman in a new userNS and join the user and
+// mount namespace of the specified PID without looking up its parent. Useful to join
+// directly the conmon process.
+func JoinDirectUserAndMountNSWithOpts(pid uint, opts *Opts) (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" {
return false, -1, nil
}
@@ -153,6 +166,12 @@ func JoinDirectUserAndMountNS(pid uint) (bool, int, error) {
}
defer userNS.Close()
+ if opts != nil && opts.Argument != "" {
+ if err := os.Setenv("_LIBPOD_ROOTLESS_ARG", opts.Argument); err != nil {
+ return false, -1, err
+ }
+ }
+
pidC := C.reexec_userns_join(C.int(userNS.Fd()), C.int(mountNS.Fd()))
if int(pidC) < 0 {
return false, -1, errors.Errorf("cannot re-exec process")
@@ -211,8 +230,16 @@ func getMinimumIDs(p string) int {
// 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
-// process.
+// process. It is a convenience function for BecomeRootInUserNSWithOpts with a default configuration.
func BecomeRootInUserNS() (bool, int, error) {
+ return BecomeRootInUserNSWithOpts(nil)
+}
+
+// BecomeRootInUserNSWithOpts re-exec podman in a new userNS. It returns whether podman was
+// re-execute 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
+// process.
+func BecomeRootInUserNSWithOpts(opts *Opts) (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_LIBPOD_USERNS_CONFIGURED") != "" {
if os.Getenv("_LIBPOD_USERNS_CONFIGURED") == "init" {
return false, 0, runInUser()
@@ -231,6 +258,12 @@ func BecomeRootInUserNS() (bool, int, error) {
defer w.Close()
defer w.Write([]byte("0"))
+ if opts != nil && opts.Argument != "" {
+ if err := os.Setenv("_LIBPOD_ROOTLESS_ARG", opts.Argument); err != nil {
+ return false, -1, err
+ }
+ }
+
pidC := C.reexec_in_user_namespace(C.int(r.Fd()))
pid := int(pidC)
if pid < 0 {
diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go
index 1823c023e..54e70961b 100644
--- a/pkg/rootless/rootless_unsupported.go
+++ b/pkg/rootless/rootless_unsupported.go
@@ -11,10 +11,18 @@ func IsRootless() bool {
return false
}
+// 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
+// process. It is a convenience function for BecomeRootInUserNSWithOpts with a default configuration.
+func BecomeRootInUserNS() (bool, int, error) {
+ return false, -1, errors.New("this function is not supported on this os")
+}
+
// BecomeRootInUserNS is a stub function that always returns false and an
// error on unsupported OS's
-func BecomeRootInUserNS() (bool, int, error) {
- return false, -1, errors.New("this function is not supported on this os1")
+func BecomeRootInUserNSWithOpts(opts *Opts) (bool, int, error) {
+ return false, -1, errors.New("this function is not supported on this os")
}
// GetRootlessUID returns the UID of the user in the parent userNS
@@ -34,18 +42,31 @@ func SkipStorageSetup() bool {
// 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 os2")
+ return false, -1, errors.New("this function is not supported on this os")
}
// JoinNSPath re-exec podman in a new userNS and join the owner user namespace of the
// specified path.
func JoinNSPath(path string) (bool, int, error) {
- return false, -1, errors.New("this function is not supported on this os3")
+ return false, -1, errors.New("this function is not supported on this os")
+}
+
+// JoinDirectUserAndMountNSWithOpts re-exec podman in a new userNS and join the user and
+// mount namespace of the specified PID without looking up its parent. Useful to join
+// directly the conmon process.
+func JoinDirectUserAndMountNSWithOpts(pid uint, opts *Opts) (bool, int, error) {
+ return false, -1, errors.New("this function is not supported on this os")
}
// JoinDirectUserAndMountNS re-exec podman in a new userNS and join the user and mount
// namespace of the specified PID without looking up its parent. Useful to join directly
-// the conmon process.
+// the conmon process. It is a convenience function for JoinDirectUserAndMountNSWithOpts
+// with a default configuration.
func JoinDirectUserAndMountNS(pid uint) (bool, int, error) {
- return false, -1, errors.New("this function is not supported on this os4")
+ return false, -1, errors.New("this function is not supported on this os")
+}
+
+// Argument returns the argument that was set for the rootless session.
+func Argument() string {
+ return ""
}