Skip to content
Closed
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
37 changes: 27 additions & 10 deletions libcontainer/configs/validate/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"golang.org/x/sys/unix"
)

var ErrInvalidConfig = errors.New("invalid configuration")

type Validator interface {
Validate(*configs.Config) error
}
Expand All @@ -26,6 +28,24 @@ func New() Validator {

type ConfigValidator struct{}

// invalidConfig type is needed to make any error returned from Validator
// to be ErrInvalidConfig.
type invalidConfig struct {
err error
}

func (e *invalidConfig) Error() string {
return ErrInvalidConfig.Error() + ": " + e.err.Error()
}

func (e *invalidConfig) Is(target error) bool {
return target == ErrInvalidConfig //nolint:errorlint // this method assumes direct comparison
}

func (e *invalidConfig) Unwrap() error {
return e.err
}

type check func(config *configs.Config) error

func (v *ConfigValidator) Validate(config *configs.Config) error {
Expand All @@ -43,7 +63,7 @@ func (v *ConfigValidator) Validate(config *configs.Config) error {
}
for _, c := range checks {
if err := c(config); err != nil {
return err
return &invalidConfig{err: err}
}
}
// Relaxed validation rules for backward compatibility
Expand All @@ -52,7 +72,7 @@ func (v *ConfigValidator) Validate(config *configs.Config) error {
}
for _, c := range warns {
if err := c(config); err != nil {
logrus.WithError(err).Warnf("invalid configuration")
logrus.WithError(err).Warn(ErrInvalidConfig)
}
}
return nil
Expand All @@ -62,20 +82,17 @@ func (v *ConfigValidator) Validate(config *configs.Config) error {
// to the container's root filesystem.
func (v *ConfigValidator) rootfs(config *configs.Config) error {
if _, err := os.Stat(config.Rootfs); err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("rootfs (%s) does not exist", config.Rootfs)
}
return err
return fmt.Errorf("invalid rootfs: %w", err)
}
cleaned, err := filepath.Abs(config.Rootfs)
if err != nil {
return err
return fmt.Errorf("invalid rootfs: %w", err)
}
if cleaned, err = filepath.EvalSymlinks(cleaned); err != nil {
return err
return fmt.Errorf("invalid rootfs: %w", err)
}
if filepath.Clean(config.Rootfs) != cleaned {
return fmt.Errorf("%s is not an absolute path or is a symlink", config.Rootfs)
return fmt.Errorf("invalid rootfs: not an absolute path, or a symlink")
}
return nil
}
Expand Down Expand Up @@ -176,7 +193,7 @@ func (v *ConfigValidator) sysctl(config *configs.Config) error {
hostnet, hostnetErr = isHostNetNS(path)
})
if hostnetErr != nil {
return hostnetErr
return fmt.Errorf("invalid netns path: %w", hostnetErr)
}
if hostnet {
return fmt.Errorf("sysctl %q not allowed in host network namespace", s)
Expand Down
1 change: 1 addition & 0 deletions libcontainer/configs/validate/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func TestValidateWithInvalidRootfs(t *testing.T) {

validator := validate.New()
err := validator.Validate(config)
t.Logf("error: %v", err)
if err == nil {
t.Error("Expected error to occur but it was nil")
}
Expand Down
2 changes: 1 addition & 1 deletion libcontainer/container_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ func (c *linuxContainer) Start(process *Process) error {
c.m.Lock()
defer c.m.Unlock()
if c.config.Cgroups.Resources.SkipDevices {
return &ConfigError{"can't start container with SkipDevices set"}
return fmt.Errorf("%w: can't start container with SkipDevices set", ErrInvalidConfig)
}
if process.Init {
if err := c.createExecFifo(); err != nil {
Expand Down
29 changes: 13 additions & 16 deletions libcontainer/error.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
package libcontainer

import "errors"
import (
"errors"

var (
ErrExist = errors.New("container with given ID already exists")
ErrInvalidID = errors.New("invalid container ID format")
ErrNotExist = errors.New("container does not exist")
ErrPaused = errors.New("container paused")
ErrRunning = errors.New("container still running")
ErrNotRunning = errors.New("container not running")
ErrNotPaused = errors.New("container not paused")
"github.com/opencontainers/runc/libcontainer/configs/validate"
)

type ConfigError struct {
details string
}

func (e *ConfigError) Error() string {
return "invalid configuration: " + e.details
}
var (
ErrExist = errors.New("container with given ID already exists")
ErrInvalidID = errors.New("invalid container ID format")
ErrNotExist = errors.New("container does not exist")
ErrPaused = errors.New("container paused")
ErrRunning = errors.New("container still running")
ErrNotRunning = errors.New("container not running")
ErrNotPaused = errors.New("container not paused")
ErrInvalidConfig = validate.ErrInvalidConfig
)
6 changes: 3 additions & 3 deletions libcontainer/factory_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,13 +251,13 @@ type LinuxFactory struct {

func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, error) {
if l.Root == "" {
return nil, &ConfigError{"invalid root"}
return nil, fmt.Errorf("%w: invalid root", ErrInvalidConfig)
}
if err := l.validateID(id); err != nil {
return nil, err
}
if err := l.Validator.Validate(config); err != nil {
return nil, &ConfigError{err.Error()}
return nil, fmt.Errorf("%w: %v", ErrInvalidConfig, err)
}
containerRoot, err := securejoin.SecureJoin(l.Root, id)
if err != nil {
Expand Down Expand Up @@ -294,7 +294,7 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err

func (l *LinuxFactory) Load(id string) (Container, error) {
if l.Root == "" {
return nil, &ConfigError{"invalid root"}
return nil, fmt.Errorf("%w: invalid root", ErrInvalidConfig)
}
// when load, we need to check id is valid or not.
if err := l.validateID(id); err != nil {
Expand Down