Skip to content

Commit

Permalink
validate: optimize capabilites check
Browse files Browse the repository at this point in the history
Signed-off-by: Ma Shimiao <[email protected]>
  • Loading branch information
Ma Shimiao committed Feb 14, 2017
1 parent 485e8cf commit 1a899a6
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 73 deletions.
3 changes: 1 addition & 2 deletions cmd/oci-runtime-tool/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import (
"fmt"
"strings"

"github.com/urfave/cli"

"github.com/opencontainers/runtime-tools/validate"
"github.com/urfave/cli"
)

var bundleValidateFlags = []cli.Flag{
Expand Down
46 changes: 7 additions & 39 deletions generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

rspec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/runtime-tools/generate/seccomp"
"github.com/opencontainers/runtime-tools/validate"
"github.com/syndtr/gocapability/capability"
)

Expand Down Expand Up @@ -754,11 +755,10 @@ func (g *Generator) AddBindMount(source, dest string, options []string) {

// SetupPrivileged sets up the privilege-related fields inside g.spec.
func (g *Generator) SetupPrivileged(privileged bool) {
if privileged {
// Add all capabilities in privileged mode.
if privileged { // Add all capabilities in privileged mode.
var finalCapList []string
for _, cap := range capability.List() {
if g.HostSpecific && cap > lastCap() {
if g.HostSpecific && cap > validate.LastCap() {
continue
}
finalCapList = append(finalCapList, fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())))
Expand All @@ -771,36 +771,6 @@ func (g *Generator) SetupPrivileged(privileged bool) {
}
}

func lastCap() capability.Cap {
last := capability.CAP_LAST_CAP
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
if last == capability.Cap(63) {
last = capability.CAP_BLOCK_SUSPEND
}

return last
}

func checkCap(c string, hostSpecific bool) error {
isValid := false
cp := strings.ToUpper(c)

for _, cap := range capability.List() {
if cp == strings.ToUpper(cap.String()) {
if hostSpecific && cap > lastCap() {
return fmt.Errorf("CAP_%s is not supported on the current host", cp)
}
isValid = true
break
}
}

if !isValid {
return fmt.Errorf("Invalid value passed for adding capability")
}
return nil
}

// ClearProcessCapabilities clear g.spec.Process.Capabilities.
func (g *Generator) ClearProcessCapabilities() {
if g.spec == nil {
Expand All @@ -811,12 +781,11 @@ func (g *Generator) ClearProcessCapabilities() {

// AddProcessCapability adds a process capability into g.spec.Process.Capabilities.
func (g *Generator) AddProcessCapability(c string) error {
if err := checkCap(c, g.HostSpecific); err != nil {
cp := strings.ToUpper(c)
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
return err
}

cp := fmt.Sprintf("CAP_%s", strings.ToUpper(c))

g.initSpec()
for _, cap := range g.spec.Process.Capabilities {
if strings.ToUpper(cap) == cp {
Expand All @@ -830,12 +799,11 @@ func (g *Generator) AddProcessCapability(c string) error {

// DropProcessCapability drops a process capability from g.spec.Process.Capabilities.
func (g *Generator) DropProcessCapability(c string) error {
if err := checkCap(c, g.HostSpecific); err != nil {
cp := strings.ToUpper(c)
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
return err
}

cp := fmt.Sprintf("CAP_%s", strings.ToUpper(c))

g.initSpec()
for i, cap := range g.spec.Process.Capabilities {
if strings.ToUpper(cap) == cp {
Expand Down
87 changes: 55 additions & 32 deletions validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,29 @@ import (
"github.com/Sirupsen/logrus"
"github.com/blang/semver"
rspec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/syndtr/gocapability/capability"
)

const specConfig = "config.json"

var (
defaultRlimits = []string{
"RLIMIT_AS",
"RLIMIT_CORE",
"RLIMIT_CPU",
"RLIMIT_FSIZE",
"RLIMIT_DATA",
"RLIMIT_STACK",
"RLIMIT_CORE",
"RLIMIT_RSS",
"RLIMIT_NPROC",
"RLIMIT_NOFILE",
"RLIMIT_MEMLOCK",
"RLIMIT_AS",
"RLIMIT_FSIZE",
"RLIMIT_LOCKS",
"RLIMIT_SIGPENDING",
"RLIMIT_MEMLOCK",
"RLIMIT_MSGQUEUE",
"RLIMIT_NICE",
"RLIMIT_NOFILE",
"RLIMIT_NPROC",
"RLIMIT_RSS",
"RLIMIT_RTPRIO",
"RLIMIT_RTTIME",
"RLIMIT_SIGPENDING",
"RLIMIT_STACK",
}
defaultCaps = []string{
"CAP_CHOWN",
Expand Down Expand Up @@ -243,19 +244,15 @@ func (v *Validator) CheckProcess() (msgs []string) {
}
}

for index := 0; index < len(process.Capabilities); index++ {
capability := process.Capabilities[index]
if !capValid(capability) {
msgs = append(msgs, fmt.Sprintf("capability %q is not valid, man capabilities(7)", process.Capabilities[index]))
for _, capability := range process.Capabilities {
if err := CapValid(capability, v.HostSpecific); err != nil {
msgs = append(msgs, fmt.Sprintf("capability %q is not valid, man capabilities(7)", capability))
}
}

for index := 0; index < len(process.Rlimits); index++ {
if !rlimitValid(process.Rlimits[index].Type) {
msgs = append(msgs, fmt.Sprintf("rlimit type %q is invalid.", process.Rlimits[index].Type))
}
if process.Rlimits[index].Hard < process.Rlimits[index].Soft {
msgs = append(msgs, fmt.Sprintf("hard limit of rlimit %s should not be less than soft limit.", process.Rlimits[index].Type))
for _, rlimit := range process.Rlimits {
if err := rlimitValid(rlimit); err != nil {
msgs = append(msgs, err.Error())
}
}

Expand Down Expand Up @@ -483,6 +480,38 @@ func (v *Validator) CheckSeccomp() (msgs []string) {
return
}

func CapValid(c string, hostSpecific bool) error {
isValid := false

if !strings.HasPrefix(c, "CAP_") {
return fmt.Errorf("capability %s must start with CAP_", c)
}
for _, cap := range capability.List() {
if c == fmt.Sprintf("CAP_%s", strings.ToUpper(cap.String())) {
if hostSpecific && cap > LastCap() {
return fmt.Errorf("CAP_%s is not supported on the current host", c)
}
isValid = true
break
}
}

if !isValid {
return fmt.Errorf("Invalid capability: %s", c)
}
return nil
}

func LastCap() capability.Cap {
last := capability.CAP_LAST_CAP
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
if last == capability.Cap(63) {
last = capability.CAP_BLOCK_SUSPEND
}

return last
}

func envValid(env string) bool {
items := strings.Split(env, "=")
if len(items) < 2 {
Expand All @@ -499,22 +528,16 @@ func envValid(env string) bool {
return true
}

func capValid(capability string) bool {
for _, val := range defaultCaps {
if val == capability {
return true
}
}
return false
}

func rlimitValid(rlimit string) bool {
func rlimitValid(rlimit rspec.Rlimit) error {
for _, val := range defaultRlimits {
if val == rlimit {
return true
if val == rlimit.Type {
if rlimit.Hard < rlimit.Soft {
return fmt.Errorf("hard limit of rlimit %s should not be less than soft limit.", rlimit.Type)
}
return nil
}
}
return false
return fmt.Errorf("rlimit type %q is invalid.", rlimit.Type)
}

func namespaceValid(ns rspec.Namespace) bool {
Expand Down

0 comments on commit 1a899a6

Please sign in to comment.