@@ -15,28 +15,29 @@ import (
1515 "github.com/Sirupsen/logrus"
1616 "github.com/blang/semver"
1717 rspec "github.com/opencontainers/runtime-spec/specs-go"
18+ "github.com/syndtr/gocapability/capability"
1819)
1920
2021const specConfig = "config.json"
2122
2223var (
2324 defaultRlimits = []string {
25+ "RLIMIT_AS" ,
26+ "RLIMIT_CORE" ,
2427 "RLIMIT_CPU" ,
25- "RLIMIT_FSIZE" ,
2628 "RLIMIT_DATA" ,
27- "RLIMIT_STACK" ,
28- "RLIMIT_CORE" ,
29- "RLIMIT_RSS" ,
30- "RLIMIT_NPROC" ,
31- "RLIMIT_NOFILE" ,
32- "RLIMIT_MEMLOCK" ,
33- "RLIMIT_AS" ,
29+ "RLIMIT_FSIZE" ,
3430 "RLIMIT_LOCKS" ,
35- "RLIMIT_SIGPENDING " ,
31+ "RLIMIT_MEMLOCK " ,
3632 "RLIMIT_MSGQUEUE" ,
3733 "RLIMIT_NICE" ,
34+ "RLIMIT_NOFILE" ,
35+ "RLIMIT_NPROC" ,
36+ "RLIMIT_RSS" ,
3837 "RLIMIT_RTPRIO" ,
3938 "RLIMIT_RTTIME" ,
39+ "RLIMIT_SIGPENDING" ,
40+ "RLIMIT_STACK" ,
4041 }
4142 defaultCaps = []string {
4243 "CAP_CHOWN" ,
@@ -56,16 +57,19 @@ var (
5657 }
5758)
5859
60+ // Validator represents a validator for runtime bundle
5961type Validator struct {
6062 spec * rspec.Spec
6163 bundlePath string
6264 HostSpecific bool
6365}
6466
67+ // NewValidator creates a Validator
6568func NewValidator (spec * rspec.Spec , bundlePath string , hostSpecific bool ) Validator {
6669 return Validator {spec : spec , bundlePath : bundlePath , HostSpecific : hostSpecific }
6770}
6871
72+ // NewValidatorFromPath creates a Validator with specified bundle path
6973func NewValidatorFromPath (bundlePath string , hostSpecific bool ) (Validator , error ) {
7074 if bundlePath == "" {
7175 return Validator {}, fmt .Errorf ("Bundle path shouldn't be empty" )
@@ -91,6 +95,7 @@ func NewValidatorFromPath(bundlePath string, hostSpecific bool) (Validator, erro
9195 return NewValidator (& spec , bundlePath , hostSpecific ), nil
9296}
9397
98+ // CheckAll checks all parts of runtime bundle
9499func (v * Validator ) CheckAll () (msgs []string ) {
95100 msgs = append (msgs , v .CheckRootfsPath ()... )
96101 msgs = append (msgs , v .CheckMandatoryFields ()... )
@@ -104,6 +109,7 @@ func (v *Validator) CheckAll() (msgs []string) {
104109 return
105110}
106111
112+ // CheckRootfsPath checks status of v.spec.Root.Path
107113func (v * Validator ) CheckRootfsPath () (msgs []string ) {
108114 logrus .Debugf ("check rootfs path" )
109115
@@ -123,6 +129,8 @@ func (v *Validator) CheckRootfsPath() (msgs []string) {
123129 return
124130
125131}
132+
133+ // CheckSemVer checks v.spec.Version
126134func (v * Validator ) CheckSemVer () (msgs []string ) {
127135 logrus .Debugf ("check semver" )
128136
@@ -138,6 +146,7 @@ func (v *Validator) CheckSemVer() (msgs []string) {
138146 return
139147}
140148
149+ // CheckPlatform checks v.spec.Platform
141150func (v * Validator ) CheckPlatform () (msgs []string ) {
142151 logrus .Debugf ("check platform" )
143152
@@ -168,6 +177,7 @@ func (v *Validator) CheckPlatform() (msgs []string) {
168177 return
169178}
170179
180+ // CheckHooks check v.spec.Hooks
171181func (v * Validator ) CheckHooks () (msgs []string ) {
172182 logrus .Debugf ("check hooks" )
173183
@@ -204,6 +214,7 @@ func checkEventHooks(hookType string, hooks []rspec.Hook, hostSpecific bool) (ms
204214 return
205215}
206216
217+ // CheckProcess checks v.spec.Process
207218func (v * Validator ) CheckProcess () (msgs []string ) {
208219 logrus .Debugf ("check process" )
209220
@@ -243,19 +254,15 @@ func (v *Validator) CheckProcess() (msgs []string) {
243254 }
244255 }
245256
246- for index := 0 ; index < len (process .Capabilities ); index ++ {
247- capability := process .Capabilities [index ]
248- if ! capValid (capability ) {
249- msgs = append (msgs , fmt .Sprintf ("capability %q is not valid, man capabilities(7)" , process .Capabilities [index ]))
257+ for _ , capability := range process .Capabilities {
258+ if err := CapValid (capability , v .HostSpecific ); err != nil {
259+ msgs = append (msgs , fmt .Sprintf ("capability %q is not valid, man capabilities(7)" , capability ))
250260 }
251261 }
252262
253- for index := 0 ; index < len (process .Rlimits ); index ++ {
254- if ! rlimitValid (process .Rlimits [index ].Type ) {
255- msgs = append (msgs , fmt .Sprintf ("rlimit type %q is invalid." , process .Rlimits [index ].Type ))
256- }
257- if process .Rlimits [index ].Hard < process .Rlimits [index ].Soft {
258- msgs = append (msgs , fmt .Sprintf ("hard limit of rlimit %s should not be less than soft limit." , process .Rlimits [index ].Type ))
263+ for _ , rlimit := range process .Rlimits {
264+ if err := rlimitValid (rlimit ); err != nil {
265+ msgs = append (msgs , err .Error ())
259266 }
260267 }
261268
@@ -311,6 +318,7 @@ func supportedMountTypes(OS string, hostSpecific bool) (map[string]bool, error)
311318 return nil , nil
312319}
313320
321+ // CheckMounts checks v.spec.Mounts
314322func (v * Validator ) CheckMounts () (msgs []string ) {
315323 logrus .Debugf ("check mounts" )
316324
@@ -335,7 +343,7 @@ func (v *Validator) CheckMounts() (msgs []string) {
335343 return
336344}
337345
338- //Linux only
346+ // CheckLinux checks v.spec.Linux
339347func (v * Validator ) CheckLinux () (msgs []string ) {
340348 logrus .Debugf ("check linux" )
341349
@@ -429,6 +437,7 @@ func (v *Validator) CheckLinux() (msgs []string) {
429437 return
430438}
431439
440+ // CheckLinuxResources checks v.spec.Linux.Resources
432441func (v * Validator ) CheckLinuxResources () (msgs []string ) {
433442 logrus .Debugf ("check linux resources" )
434443
@@ -445,6 +454,7 @@ func (v *Validator) CheckLinuxResources() (msgs []string) {
445454 return
446455}
447456
457+ // CheckSeccomp checkc v.spec.Linux.Seccomp
448458func (v * Validator ) CheckSeccomp () (msgs []string ) {
449459 logrus .Debugf ("check linux seccomp" )
450460
@@ -483,6 +493,40 @@ func (v *Validator) CheckSeccomp() (msgs []string) {
483493 return
484494}
485495
496+ // CapValid checks whether a capability is valid
497+ func CapValid (c string , hostSpecific bool ) error {
498+ isValid := false
499+
500+ if ! strings .HasPrefix (c , "CAP_" ) {
501+ return fmt .Errorf ("capability %s must start with CAP_" , c )
502+ }
503+ for _ , cap := range capability .List () {
504+ if c == fmt .Sprintf ("CAP_%s" , strings .ToUpper (cap .String ())) {
505+ if hostSpecific && cap > LastCap () {
506+ return fmt .Errorf ("CAP_%s is not supported on the current host" , c )
507+ }
508+ isValid = true
509+ break
510+ }
511+ }
512+
513+ if ! isValid {
514+ return fmt .Errorf ("Invalid capability: %s" , c )
515+ }
516+ return nil
517+ }
518+
519+ // LastCap return last cap of system
520+ func LastCap () capability.Cap {
521+ last := capability .CAP_LAST_CAP
522+ // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
523+ if last == capability .Cap (63 ) {
524+ last = capability .CAP_BLOCK_SUSPEND
525+ }
526+
527+ return last
528+ }
529+
486530func envValid (env string ) bool {
487531 items := strings .Split (env , "=" )
488532 if len (items ) < 2 {
@@ -499,22 +543,16 @@ func envValid(env string) bool {
499543 return true
500544}
501545
502- func capValid (capability string ) bool {
503- for _ , val := range defaultCaps {
504- if val == capability {
505- return true
506- }
546+ func rlimitValid (rlimit rspec.Rlimit ) error {
547+ if rlimit .Hard < rlimit .Soft {
548+ return fmt .Errorf ("hard limit of rlimit %s should not be less than soft limit" , rlimit .Type )
507549 }
508- return false
509- }
510-
511- func rlimitValid (rlimit string ) bool {
512550 for _ , val := range defaultRlimits {
513- if val == rlimit {
514- return true
551+ if val == rlimit . Type {
552+ return nil
515553 }
516554 }
517- return false
555+ return fmt . Errorf ( "rlimit type %q is invalid" , rlimit . Type )
518556}
519557
520558func namespaceValid (ns rspec.Namespace ) bool {
@@ -662,6 +700,7 @@ func checkMandatory(obj interface{}) (msgs []string) {
662700 return
663701}
664702
703+ // CheckMandatoryFields checks mandatory field of container's config file
665704func (v * Validator ) CheckMandatoryFields () []string {
666705 logrus .Debugf ("check mandatory fields" )
667706
0 commit comments