Skip to content

Commit

Permalink
rootless: add rootless logic
Browse files Browse the repository at this point in the history
Add the ability to check whether kata is running rootlessly or
not. Add the setup of the rootless directory located in the dir
/run/user/<UID> directory.

Fixes: kata-containers#1874

Signed-off-by: Gabi Beyer <[email protected]>
Gabi Beyer committed Jul 30, 2019
1 parent 3255640 commit 07b4fbd
Showing 3 changed files with 177 additions and 0 deletions.
10 changes: 10 additions & 0 deletions cli/main.go
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@ import (
"syscall"

"github.com/kata-containers/runtime/pkg/katautils"
"github.com/kata-containers/runtime/pkg/rootless"
"github.com/kata-containers/runtime/pkg/signals"
vc "github.com/kata-containers/runtime/virtcontainers"
vf "github.com/kata-containers/runtime/virtcontainers/factory"
@@ -241,6 +242,9 @@ func setExternalLoggers(ctx context.Context, logger *logrus.Entry) {

// Set the katautils package logger
katautils.SetLogger(ctx, logger, originalLoggerLevel)

// Set the rootless package logger
rootless.SetLogger(ctx, logger)
}

// beforeSubcommands is the function to perform preliminary checks
@@ -337,6 +341,12 @@ func beforeSubcommands(c *cli.Context) error {

kataLog.WithFields(fields).Info()

// Check if running rootlessly, and setup for rootless execution
err = rootless.SetRootless()
if err != nil {
fatal(err)
}

// make the data accessible to the sub-commands.
c.App.Metadata["runtimeConfig"] = runtimeConfig
c.App.Metadata["configFile"] = configFile
79 changes: 79 additions & 0 deletions pkg/rootless/rootless.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//

package rootless

import (
"bufio"
"context"
"io"
"os"
"strings"

"github.com/sirupsen/logrus"
)

var (
isRootless bool
rootlessDir = os.Getenv("XDG_RUNTIME_DIR")
uidMapPath = "/proc/self/uid_map"

rootlessLog = logrus.WithFields(logrus.Fields{
"source": "rootless",
})
)

// SetLogger sets up a logger for the rootless pkg
func SetLogger(ctx context.Context, logger *logrus.Entry) {
fields := rootlessLog.Data
rootlessLog = logger.WithFields(fields)
}

// SetRootless reads a uid_map file, compares the UID of the
// user inside the container vs on the host. If the host UID
// is not root, but the container ID is, it can be determined
// the user is running rootlessly.
func SetRootless() error {
file, err := os.Open(uidMapPath)
if err != nil {
return err
}
defer file.Close()

buf := bufio.NewReader(file)
for {
line, _, err := buf.ReadLine()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
if line == nil {
return nil
}

// if the container id (id[0]) is 0 (root inside the container)
// has a mapping to the host id (id[1]) that is not root, then
// it can be determined that the host user is running rootless
ids := strings.Fields(string(line))
if ids[0] == "0" && ids[1] != "0" {
rootlessLog.Infof("Running as rootless")
isRootless = true
return nil
}
}
}

// IsRootless states whether kata is being ran with root or not
func IsRootless() bool {
return isRootless
}

// GetRootlessDir returns the path to the location for rootless
// container and sandbox storage
func GetRootlessDir() string {
return rootlessDir
}
88 changes: 88 additions & 0 deletions pkg/rootless/rootless_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) 2019 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//

package rootless

import (
"io/ioutil"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
)

var uidMapPathStore = uidMapPath

func createTestUIDMapFile(input string) error {
f, err := os.Create(uidMapPath)
if err != nil {
return err
}
defer f.Close()

_, err = f.WriteString(input)
if err != nil {
return err
}

return nil
}

// TestSetRootlessRootlessUID1000 tests that isRootless is set to
// true when a host UID is not 0
func TestSetRootlessRootlessUID1000(t *testing.T) {
assert := assert.New(t)

// by default isRootless should be set to false initially
assert.False(IsRootless())

tmpDir, err := ioutil.TempDir("", "")
assert.NoError(err)

uidMapPath = filepath.Join(tmpDir, "testUIDMapFile")
defer func() {
uidMapPath = uidMapPathStore
os.RemoveAll(tmpDir)
isRootless = false
}()

mapping := "\t0\t1000\t5555"
err = createTestUIDMapFile(mapping)
assert.NoError(err)

err = SetRootless()
assert.NoError(err)

assert.True(IsRootless())
}

// TestSetRootlessRootUID0 tests that isRootless is not set when
// the host UID is 0
func TestSetRootlessRootUID0(t *testing.T) {
assert := assert.New(t)

// by default isRootless should be set to false initially
assert.False(IsRootless())

tmpDir, err := ioutil.TempDir("", "")
assert.NoError(err)

uidMapPath = filepath.Join(tmpDir, "testUIDMapFile")
defer func() {
uidMapPath = uidMapPathStore
os.RemoveAll(uidMapPath)
isRootless = false
}()

mapping := "\t0\t0\t5555"
err = createTestUIDMapFile(mapping)
assert.NoError(err)

err = SetRootless()
assert.NoError(err)

assert.False(IsRootless())
}

0 comments on commit 07b4fbd

Please sign in to comment.