Skip to content

Commit 1a899a6

Browse files
author
Ma Shimiao
committed
validate: optimize capabilites check
Signed-off-by: Ma Shimiao <[email protected]>
1 parent 485e8cf commit 1a899a6

File tree

3 files changed

+63
-73
lines changed

3 files changed

+63
-73
lines changed

cmd/oci-runtime-tool/validate.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@ import (
44
"fmt"
55
"strings"
66

7-
"github.com/urfave/cli"
8-
97
"github.com/opencontainers/runtime-tools/validate"
8+
"github.com/urfave/cli"
109
)
1110

1211
var bundleValidateFlags = []cli.Flag{

generate/generate.go

Lines changed: 7 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
rspec "github.com/opencontainers/runtime-spec/specs-go"
1313
"github.com/opencontainers/runtime-tools/generate/seccomp"
14+
"github.com/opencontainers/runtime-tools/validate"
1415
"github.com/syndtr/gocapability/capability"
1516
)
1617

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

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

774-
func lastCap() capability.Cap {
775-
last := capability.CAP_LAST_CAP
776-
// hack for RHEL6 which has no /proc/sys/kernel/cap_last_cap
777-
if last == capability.Cap(63) {
778-
last = capability.CAP_BLOCK_SUSPEND
779-
}
780-
781-
return last
782-
}
783-
784-
func checkCap(c string, hostSpecific bool) error {
785-
isValid := false
786-
cp := strings.ToUpper(c)
787-
788-
for _, cap := range capability.List() {
789-
if cp == strings.ToUpper(cap.String()) {
790-
if hostSpecific && cap > lastCap() {
791-
return fmt.Errorf("CAP_%s is not supported on the current host", cp)
792-
}
793-
isValid = true
794-
break
795-
}
796-
}
797-
798-
if !isValid {
799-
return fmt.Errorf("Invalid value passed for adding capability")
800-
}
801-
return nil
802-
}
803-
804774
// ClearProcessCapabilities clear g.spec.Process.Capabilities.
805775
func (g *Generator) ClearProcessCapabilities() {
806776
if g.spec == nil {
@@ -811,12 +781,11 @@ func (g *Generator) ClearProcessCapabilities() {
811781

812782
// AddProcessCapability adds a process capability into g.spec.Process.Capabilities.
813783
func (g *Generator) AddProcessCapability(c string) error {
814-
if err := checkCap(c, g.HostSpecific); err != nil {
784+
cp := strings.ToUpper(c)
785+
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
815786
return err
816787
}
817788

818-
cp := fmt.Sprintf("CAP_%s", strings.ToUpper(c))
819-
820789
g.initSpec()
821790
for _, cap := range g.spec.Process.Capabilities {
822791
if strings.ToUpper(cap) == cp {
@@ -830,12 +799,11 @@ func (g *Generator) AddProcessCapability(c string) error {
830799

831800
// DropProcessCapability drops a process capability from g.spec.Process.Capabilities.
832801
func (g *Generator) DropProcessCapability(c string) error {
833-
if err := checkCap(c, g.HostSpecific); err != nil {
802+
cp := strings.ToUpper(c)
803+
if err := validate.CapValid(cp, g.HostSpecific); err != nil {
834804
return err
835805
}
836806

837-
cp := fmt.Sprintf("CAP_%s", strings.ToUpper(c))
838-
839807
g.initSpec()
840808
for i, cap := range g.spec.Process.Capabilities {
841809
if strings.ToUpper(cap) == cp {

validate/validate.go

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -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

2021
const specConfig = "config.json"
2122

2223
var (
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+
486515
func 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

520543
func namespaceValid(ns rspec.Namespace) bool {

0 commit comments

Comments
 (0)