diff --git a/libcontainer/configs/validate/rootless.go b/libcontainer/configs/validate/rootless.go index 7afdb4310f9..99ab3f8f389 100644 --- a/libcontainer/configs/validate/rootless.go +++ b/libcontainer/configs/validate/rootless.go @@ -2,7 +2,7 @@ package validate import ( "errors" - "fmt" + "strconv" "strings" "github.com/opencontainers/runc/libcontainer/configs" @@ -51,9 +51,8 @@ func rootlessEUIDMappings(config *configs.Config) error { return nil } -// mount verifies that the user isn't trying to set up any mounts they don't have -// the rights to do. In addition, it makes sure that no mount has a `uid=` or -// `gid=` option that doesn't resolve to root. +// rootlessEUIDMount verifies that all mounts have valid uid=/gid= options, +// i.e. their arguments has proper ID mappings. func rootlessEUIDMount(config *configs.Config) error { // XXX: We could whitelist allowed devices at this point, but I'm not // convinced that's a good idea. The kernel is the best arbiter of @@ -63,10 +62,9 @@ func rootlessEUIDMount(config *configs.Config) error { // Check that the options list doesn't contain any uid= or gid= entries // that don't resolve to root. for _, opt := range strings.Split(mount.Data, ",") { - if strings.HasPrefix(opt, "uid=") { - var uid int - n, err := fmt.Sscanf(opt, "uid=%d", &uid) - if n != 1 || err != nil { + if str := strings.TrimPrefix(opt, "uid="); len(str) < len(opt) { + uid, err := strconv.Atoi(str) + if err != nil { // Ignore unknown mount options. continue } @@ -75,10 +73,9 @@ func rootlessEUIDMount(config *configs.Config) error { } } - if strings.HasPrefix(opt, "gid=") { - var gid int - n, err := fmt.Sscanf(opt, "gid=%d", &gid) - if n != 1 || err != nil { + if str := strings.TrimPrefix(opt, "gid="); len(str) < len(opt) { + gid, err := strconv.Atoi(str) + if err != nil { // Ignore unknown mount options. continue } diff --git a/libcontainer/configs/validate/rootless_test.go b/libcontainer/configs/validate/rootless_test.go index 0657abf48dc..0e8df6eb297 100644 --- a/libcontainer/configs/validate/rootless_test.go +++ b/libcontainer/configs/validate/rootless_test.go @@ -141,3 +141,24 @@ func TestValidateRootlessEUIDMountGid(t *testing.T) { t.Errorf("Expected error to occur when setting gid=11 in mount options and GidMapping[0].size is 10") } } + +func BenchmarkRootlessEUIDMount(b *testing.B) { + config := rootlessEUIDConfig() + config.GidMappings[0].Size = 10 + config.Mounts = []*configs.Mount{ + { + Source: "devpts", + Destination: "/dev/pts", + Device: "devpts", + Data: "newinstance,ptmxmode=0666,mode=0620,uid=0,gid=5", + }, + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + err := rootlessEUIDMount(config) + if err != nil { + b.Fatal(err) + } + } +}