Skip to content

Commit

Permalink
Add rootless package from containers/libpod
Browse files Browse the repository at this point in the history
Add rootless package to kata in order to include some rootless
functionalities including: 1. Determining whether an exectution is
being ran rootless or not, 2. Get the rootless UID of a process,
and 3. Get the rootless runtime directory for nonroot users.

Signed-off-by: Gabi Beyer <[email protected]>
  • Loading branch information
Gabi Beyer committed Jun 25, 2019
1 parent 829ac72 commit 1a26b16
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 0 deletions.
18 changes: 18 additions & 0 deletions pkg/rootless/rootless.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#define _GNU_SOURCE
#include <sys/types.h>

static uid_t rootless_uid_init;
static gid_t rootless_gid_init;

uid_t
rootless_uid ()
{
return rootless_uid_init;
}

uid_t
rootless_gid ()
{
return rootless_gid_init;
}

98 changes: 98 additions & 0 deletions pkg/rootless/rootless.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package rootless

import (
"fmt"
"os"
"path/filepath"
"strconv"
"sync"
"syscall"

"github.com/pkg/errors"
)

/*
#include <sys/types.h>
extern uid_t rootless_uid();
extern uid_t rootless_gid();
*/
import "C"

var (
isRootlessOnce sync.Once
isRootless bool

rootlessRuntimeDirOnce sync.Once
rootlessRuntimeDir string
)

// IsRootless tells us if we are running in rootless mode
func IsRootless() bool {
isRootlessOnce.Do(func() {
rootlessUIDInit := int(C.rootless_uid())
rootlessGIDInit := int(C.rootless_gid())
if rootlessUIDInit != 0 {
// This happens if we joined the user+mount namespace as part of
os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done")
os.Setenv("_CONTAINERS_ROOTLESS_UID", fmt.Sprintf("%d", rootlessUIDInit))
os.Setenv("_CONTAINERS_ROOTLESS_GID", fmt.Sprintf("%d", rootlessGIDInit))
}
isRootless = os.Geteuid() != 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != ""
})
return isRootless
}

// GetRootlessUID returns the UID of the user in the parent userNS
func GetRootlessUID() int {
uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID")
if uidEnv != "" {
u, _ := strconv.Atoi(uidEnv)
return u
}
return os.Geteuid()
}

// GetRootlessRuntimeDir returns the runtime directory when running as non root
func GetRootlessRuntimeDir() (string, error) {
var rootlessRuntimeDirError error

rootlessRuntimeDirOnce.Do(func() {
runtimeDir := os.Getenv("XDG_RUNTIME_DIR")
uid := fmt.Sprintf("%d", GetRootlessUID())
if runtimeDir == "" {
tmpDir := filepath.Join("/run", "user", uid)
os.MkdirAll(tmpDir, 0700)
st, err := os.Stat(tmpDir)
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
runtimeDir = tmpDir
}
}
if runtimeDir == "" {
tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("run-%s", uid))
os.MkdirAll(tmpDir, 0700)
st, err := os.Stat(tmpDir)
if err == nil && int(st.Sys().(*syscall.Stat_t).Uid) == os.Geteuid() && st.Mode().Perm() == 0700 {
runtimeDir = tmpDir
}
}
if runtimeDir == "" {
home := os.Getenv("HOME")
if home == "" {
rootlessRuntimeDirError = fmt.Errorf("neither XDG_RUNTIME_DIR nor HOME was set non-empty")
return
}
resolvedHome, err := filepath.EvalSymlinks(home)
if err != nil {
rootlessRuntimeDirError = errors.Wrapf(err, "cannot resolve %s", home)
return
}
runtimeDir = filepath.Join(resolvedHome, "rundir")
}
rootlessRuntimeDir = runtimeDir
})

if rootlessRuntimeDirError != nil {
return "", rootlessRuntimeDirError
}
return rootlessRuntimeDir, nil
}

0 comments on commit 1a26b16

Please sign in to comment.