@@ -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" ,
@@ -243,19 +244,15 @@ func (v *Validator) CheckProcess() (msgs []string) {
243244 }
244245 }
245246
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 ]))
247+ for _ , capability := range process .Capabilities {
248+ if err := CapValid (capability , v .HostSpecific ); err != nil {
249+ msgs = append (msgs , fmt .Sprintf ("capability %q is not valid, man capabilities(7)" , capability ))
250250 }
251251 }
252252
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 ))
253+ for _ , rlimit := range process .Rlimits {
254+ if err := rlimitValid (rlimit ); err != nil {
255+ msgs = append (msgs , err .Error ())
259256 }
260257 }
261258
@@ -483,6 +480,38 @@ func (v *Validator) CheckSeccomp() (msgs []string) {
483480 return
484481}
485482
483+ func CapValid (c string , hostSpecific bool ) error {
484+ isValid := false
485+
486+ if ! strings .HasPrefix (c , "CAP_" ) {
487+ return fmt .Errorf ("capability %s must start with CAP_" , c )
488+ }
489+ for _ , cap := range capability .List () {
490+ if c == fmt .Sprintf ("CAP_%s" , strings .ToUpper (cap .String ())) {
491+ if hostSpecific && cap > LastCap () {
492+ return fmt .Errorf ("CAP_%s is not supported on the current host" , c )
493+ }
494+ isValid = true
495+ break
496+ }
497+ }
498+
499+ if ! isValid {
500+ return fmt .Errorf ("Invalid capability: %s" , c )
501+ }
502+ return nil
503+ }
504+
505+ func LastCap () capability.Cap {
506+ last := capability .CAP_LAST_CAP
507+ // hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
508+ if last == capability .Cap (63 ) {
509+ last = capability .CAP_BLOCK_SUSPEND
510+ }
511+
512+ return last
513+ }
514+
486515func envValid (env string ) bool {
487516 items := strings .Split (env , "=" )
488517 if len (items ) < 2 {
@@ -499,22 +528,16 @@ func envValid(env string) bool {
499528 return true
500529}
501530
502- func capValid (capability string ) bool {
503- for _ , val := range defaultCaps {
504- if val == capability {
505- return true
506- }
507- }
508- return false
509- }
510-
511- func rlimitValid (rlimit string ) bool {
531+ func rlimitValid (rlimit rspec.Rlimit ) error {
512532 for _ , val := range defaultRlimits {
513- if val == rlimit {
514- return true
533+ if val == rlimit .Type {
534+ if rlimit .Hard < rlimit .Soft {
535+ return fmt .Errorf ("hard limit of rlimit %s should not be less than soft limit." , rlimit .Type )
536+ }
537+ return nil
515538 }
516539 }
517- return false
540+ return fmt . Errorf ( "rlimit type %q is invalid." , rlimit . Type )
518541}
519542
520543func namespaceValid (ns rspec.Namespace ) bool {
0 commit comments