Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Factory cleanup #3354

Merged
merged 6 commits into from
Feb 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion libcontainer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ Then to create a container you first have to initialize an instance of a factory
that will handle the creation and initialization for a container.

```go
factory, err := libcontainer.New("/var/lib/container", libcontainer.InitArgs(os.Args[0], "init"))
factory, err := libcontainer.New("/var/lib/container")
if err != nil {
logrus.Fatal(err)
return
Expand Down
4 changes: 2 additions & 2 deletions libcontainer/configs/validate/rootless.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
"github.com/opencontainers/runc/libcontainer/configs"
)

// rootlessEUID makes sure that the config can be applied when runc
// rootlessEUIDCheck makes sure that the config can be applied when runc
// is being executed as a non-root user (euid != 0) in the current user namespace.
func (v *ConfigValidator) rootlessEUID(config *configs.Config) error {
func rootlessEUIDCheck(config *configs.Config) error {
if !config.RootlessEUID {
return nil
}
Expand Down
40 changes: 14 additions & 26 deletions libcontainer/configs/validate/rootless_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,42 +34,34 @@ func rootlessEUIDConfig() *configs.Config {
}

func TestValidateRootlessEUID(t *testing.T) {
validator := New()

config := rootlessEUIDConfig()
if err := validator.Validate(config); err != nil {
if err := Validate(config); err != nil {
t.Errorf("Expected error to not occur: %+v", err)
}
}

/* rootlessEUIDMappings */

func TestValidateRootlessEUIDUserns(t *testing.T) {
validator := New()

config := rootlessEUIDConfig()
config.Namespaces = nil
if err := validator.Validate(config); err == nil {
if err := Validate(config); err == nil {
t.Errorf("Expected error to occur if user namespaces not set")
}
}

func TestValidateRootlessEUIDMappingUid(t *testing.T) {
validator := New()

config := rootlessEUIDConfig()
config.UidMappings = nil
if err := validator.Validate(config); err == nil {
if err := Validate(config); err == nil {
t.Errorf("Expected error to occur if no uid mappings provided")
}
}

func TestValidateNonZeroEUIDMappingGid(t *testing.T) {
validator := New()

config := rootlessEUIDConfig()
config.GidMappings = nil
if err := validator.Validate(config); err == nil {
if err := Validate(config); err == nil {
t.Errorf("Expected error to occur if no gid mappings provided")
}
}
Expand All @@ -78,8 +70,6 @@ func TestValidateNonZeroEUIDMappingGid(t *testing.T) {

func TestValidateRootlessEUIDMountUid(t *testing.T) {
config := rootlessEUIDConfig()
validator := New()

config.Mounts = []*configs.Mount{
{
Source: "devpts",
Expand All @@ -88,37 +78,35 @@ func TestValidateRootlessEUIDMountUid(t *testing.T) {
},
}

if err := validator.Validate(config); err != nil {
if err := Validate(config); err != nil {
t.Errorf("Expected error to not occur when uid= not set in mount options: %+v", err)
}

config.Mounts[0].Data = "uid=5"
if err := validator.Validate(config); err == nil {
if err := Validate(config); err == nil {
t.Errorf("Expected error to occur when setting uid=5 in mount options")
}

config.Mounts[0].Data = "uid=0"
if err := validator.Validate(config); err != nil {
if err := Validate(config); err != nil {
t.Errorf("Expected error to not occur when setting uid=0 in mount options: %+v", err)
}

config.Mounts[0].Data = "uid=2"
config.UidMappings[0].Size = 10
if err := validator.Validate(config); err != nil {
if err := Validate(config); err != nil {
t.Errorf("Expected error to not occur when setting uid=2 in mount options and UidMapping[0].size is 10")
}

config.Mounts[0].Data = "uid=20"
config.UidMappings[0].Size = 10
if err := validator.Validate(config); err == nil {
if err := Validate(config); err == nil {
t.Errorf("Expected error to occur when setting uid=20 in mount options and UidMapping[0].size is 10")
}
}

func TestValidateRootlessEUIDMountGid(t *testing.T) {
config := rootlessEUIDConfig()
validator := New()

config.Mounts = []*configs.Mount{
{
Source: "devpts",
Expand All @@ -127,29 +115,29 @@ func TestValidateRootlessEUIDMountGid(t *testing.T) {
},
}

if err := validator.Validate(config); err != nil {
if err := Validate(config); err != nil {
t.Errorf("Expected error to not occur when gid= not set in mount options: %+v", err)
}

config.Mounts[0].Data = "gid=5"
if err := validator.Validate(config); err == nil {
if err := Validate(config); err == nil {
t.Errorf("Expected error to occur when setting gid=5 in mount options")
}

config.Mounts[0].Data = "gid=0"
if err := validator.Validate(config); err != nil {
if err := Validate(config); err != nil {
t.Errorf("Expected error to not occur when setting gid=0 in mount options: %+v", err)
}

config.Mounts[0].Data = "gid=5"
config.GidMappings[0].Size = 10
if err := validator.Validate(config); err != nil {
if err := Validate(config); err != nil {
t.Errorf("Expected error to not occur when setting gid=5 in mount options and GidMapping[0].size is 10")
}

config.Mounts[0].Data = "gid=11"
config.GidMappings[0].Size = 10
if err := validator.Validate(config); err == nil {
if err := Validate(config); err == nil {
t.Errorf("Expected error to occur when setting gid=11 in mount options and GidMapping[0].size is 10")
}
}
55 changes: 21 additions & 34 deletions libcontainer/configs/validate/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,19 @@ import (
"golang.org/x/sys/unix"
)

type Validator interface {
Validate(*configs.Config) error
}

func New() Validator {
return &ConfigValidator{}
}

type ConfigValidator struct{}

type check func(config *configs.Config) error

func (v *ConfigValidator) Validate(config *configs.Config) error {
func Validate(config *configs.Config) error {
checks := []check{
v.cgroups,
v.rootfs,
v.network,
v.hostname,
v.security,
v.usernamespace,
v.cgroupnamespace,
v.sysctl,
v.intelrdt,
v.rootlessEUID,
cgroupsCheck,
rootfs,
network,
hostname,
security,
namespaces,
sysctl,
intelrdtCheck,
rootlessEUIDCheck,
}
for _, c := range checks {
if err := c(config); err != nil {
Expand All @@ -48,7 +37,7 @@ func (v *ConfigValidator) Validate(config *configs.Config) error {
}
// Relaxed validation rules for backward compatibility
warns := []check{
v.mounts, // TODO (runc v1.x.x): make this an error instead of a warning
mounts, // TODO (runc v1.x.x): make this an error instead of a warning
}
for _, c := range warns {
if err := c(config); err != nil {
Expand All @@ -60,7 +49,7 @@ func (v *ConfigValidator) Validate(config *configs.Config) error {

// rootfs validates if the rootfs is an absolute path and is not a symlink
// to the container's root filesystem.
func (v *ConfigValidator) rootfs(config *configs.Config) error {
func rootfs(config *configs.Config) error {
if _, err := os.Stat(config.Rootfs); err != nil {
return fmt.Errorf("invalid rootfs: %w", err)
}
Expand All @@ -77,7 +66,7 @@ func (v *ConfigValidator) rootfs(config *configs.Config) error {
return nil
}

func (v *ConfigValidator) network(config *configs.Config) error {
func network(config *configs.Config) error {
if !config.Namespaces.Contains(configs.NEWNET) {
if len(config.Networks) > 0 || len(config.Routes) > 0 {
return errors.New("unable to apply network settings without a private NET namespace")
Expand All @@ -86,14 +75,14 @@ func (v *ConfigValidator) network(config *configs.Config) error {
return nil
}

func (v *ConfigValidator) hostname(config *configs.Config) error {
func hostname(config *configs.Config) error {
if config.Hostname != "" && !config.Namespaces.Contains(configs.NEWUTS) {
return errors.New("unable to set hostname without a private UTS namespace")
}
return nil
}

func (v *ConfigValidator) security(config *configs.Config) error {
func security(config *configs.Config) error {
// restrict sys without mount namespace
if (len(config.MaskPaths) > 0 || len(config.ReadonlyPaths) > 0) &&
!config.Namespaces.Contains(configs.NEWNS) {
Expand All @@ -106,7 +95,7 @@ func (v *ConfigValidator) security(config *configs.Config) error {
return nil
}

func (v *ConfigValidator) usernamespace(config *configs.Config) error {
func namespaces(config *configs.Config) error {
if config.Namespaces.Contains(configs.NEWUSER) {
if _, err := os.Stat("/proc/self/ns/user"); os.IsNotExist(err) {
return errors.New("USER namespaces aren't enabled in the kernel")
Expand All @@ -116,15 +105,13 @@ func (v *ConfigValidator) usernamespace(config *configs.Config) error {
return errors.New("User namespace mappings specified, but USER namespace isn't enabled in the config")
}
}
return nil
}

func (v *ConfigValidator) cgroupnamespace(config *configs.Config) error {
if config.Namespaces.Contains(configs.NEWCGROUP) {
if _, err := os.Stat("/proc/self/ns/cgroup"); os.IsNotExist(err) {
return errors.New("cgroup namespaces aren't enabled in the kernel")
}
}

return nil
}

Expand Down Expand Up @@ -161,7 +148,7 @@ func convertSysctlVariableToDotsSeparator(val string) string {
// sysctl validates that the specified sysctl keys are valid or not.
// /proc/sys isn't completely namespaced and depending on which namespaces
// are specified, a subset of sysctls are permitted.
func (v *ConfigValidator) sysctl(config *configs.Config) error {
func sysctl(config *configs.Config) error {
validSysctlMap := map[string]bool{
"kernel.msgmax": true,
"kernel.msgmnb": true,
Expand Down Expand Up @@ -227,7 +214,7 @@ func (v *ConfigValidator) sysctl(config *configs.Config) error {
return nil
}

func (v *ConfigValidator) intelrdt(config *configs.Config) error {
func intelrdtCheck(config *configs.Config) error {
if config.IntelRdt != nil {
if !intelrdt.IsCATEnabled() && !intelrdt.IsMBAEnabled() {
return errors.New("intelRdt is specified in config, but Intel RDT is not supported or enabled")
Expand All @@ -248,7 +235,7 @@ func (v *ConfigValidator) intelrdt(config *configs.Config) error {
return nil
}

func (v *ConfigValidator) cgroups(config *configs.Config) error {
func cgroupsCheck(config *configs.Config) error {
c := config.Cgroups
if c == nil {
return nil
Expand Down Expand Up @@ -277,7 +264,7 @@ func (v *ConfigValidator) cgroups(config *configs.Config) error {
return nil
}

func (v *ConfigValidator) mounts(config *configs.Config) error {
func mounts(config *configs.Config) error {
for _, m := range config.Mounts {
if !filepath.IsAbs(m.Destination) {
return fmt.Errorf("invalid mount %+v: mount destination not absolute", m)
Expand Down
Loading