forked from kata-containers/runtime
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]>
- Loading branch information
Showing
3 changed files
with
193 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// Copyright (c) 2019 Intel Corporation | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
|
||
package rootless | ||
|
||
import ( | ||
"bufio" | ||
"context" | ||
"io" | ||
"os" | ||
"strings" | ||
"sync" | ||
|
||
"github.com/sirupsen/logrus" | ||
) | ||
|
||
var ( | ||
// initRootless states whether the isRootless variable | ||
// has been set yet | ||
initRootless bool | ||
|
||
// isRootless states whether execution is rootless or not | ||
isRootless bool | ||
|
||
// lock for the initRootless and isRootless variables | ||
rLock sync.Mutex | ||
|
||
// XDG_RUNTIME_DIR defines the base directory relative to | ||
// which user-specific non-essential runtime files are stored. | ||
rootlessDir = os.Getenv("XDG_RUNTIME_DIR") | ||
|
||
// uidMapPath defines the location of the uid_map file to | ||
// determine whether a user is root or not | ||
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 { | ||
initRootless = true | ||
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 { | ||
rLock.Lock() | ||
if !initRootless { | ||
err := setRootless() | ||
if err != nil { | ||
rootlessLog.Errorf("Unable to determine if running rootless") | ||
} | ||
} | ||
rLock.Unlock() | ||
return isRootless | ||
} | ||
|
||
// GetRootlessDir returns the path to the location for rootless | ||
// container and sandbox storage | ||
func GetRootlessDir() string { | ||
return rootlessDir | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
// 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 | ||
} | ||
|
||
// TestIstRootlessRootlessUID1000 tests that isRootless is set to | ||
// true when a host UID is not 0 | ||
func TestIsRootlessRootlessUID1000(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) | ||
|
||
// make call to IsRootless, this should also call | ||
// SetRootless | ||
assert.True(IsRootless()) | ||
} | ||
|
||
// TestIsRootlessRootUID0 tests that isRootless is not set when | ||
// the host UID is 0 | ||
func TestIsRootlessRootUID0(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) | ||
|
||
// make call to IsRootless, this should also call | ||
// SetRootless | ||
assert.False(IsRootless()) | ||
} |