diff --git a/libcontainer/cgroups/devices/devices_emulator.go b/libcontainer/cgroups/devices/devices_emulator.go index 941169ecf..b5ff2dfe9 100644 --- a/libcontainer/cgroups/devices/devices_emulator.go +++ b/libcontainer/cgroups/devices/devices_emulator.go @@ -22,12 +22,11 @@ package devices import ( "bufio" - "errors" "fmt" "io" - "regexp" "sort" "strconv" + "strings" "github.com/opencontainers/runc/libcontainer/devices" ) @@ -79,19 +78,21 @@ func (e *Emulator) IsAllowAll() bool { return e.IsBlacklist() && len(e.rules) == 0 } -var devicesListRegexp = regexp.MustCompile(`^([abc])\s+(\d+|\*):(\d+|\*)\s+([rwm]+)$`) - func parseLine(line string) (*deviceRule, error) { - matches := devicesListRegexp.FindStringSubmatch(line) - if matches == nil { - return nil, errors.New("line doesn't match devices.list format") + // Input: node major:minor perms. + fields := strings.FieldsFunc(line, func(r rune) bool { + return r == ' ' || r == ':' + }) + if len(fields) != 4 { + return nil, fmt.Errorf("malformed devices.list rule %s", line) } + var ( rule deviceRule - node = devices.Type(matches[1]) - major = matches[2] - minor = matches[3] - perms = matches[4] + node = devices.Type(fields[0]) + major = fields[1] + minor = fields[2] + perms = fields[3] ) // Parse the node type. @@ -105,7 +106,6 @@ func parseLine(line string) (*deviceRule, error) { case devices.BlockDevice, devices.CharDevice: rule.meta.node = node default: - // Should never happen! return nil, fmt.Errorf("unknown device type %q", node) } @@ -134,7 +134,6 @@ func parseLine(line string) (*deviceRule, error) { // Parse the access permissions. rule.perms = devices.Permissions(perms) if !rule.perms.IsValid() || rule.perms.IsEmpty() { - // Should never happen! return nil, fmt.Errorf("parse access mode: contained unknown modes or is empty: %q", perms) } diff --git a/libcontainer/cgroups/devices/devices_emulator_test.go b/libcontainer/cgroups/devices/devices_emulator_test.go index 5dbcbdee6..4dac242cf 100644 --- a/libcontainer/cgroups/devices/devices_emulator_test.go +++ b/libcontainer/cgroups/devices/devices_emulator_test.go @@ -19,8 +19,10 @@ package devices import ( + "bufio" "bytes" "reflect" + "strings" "testing" "github.com/opencontainers/runc/libcontainer/devices" @@ -1112,3 +1114,31 @@ func TestDeviceEmulatorTransitionFromBlacklist(t *testing.T) { func TestDeviceEmulatorTransitionFromWhitelist(t *testing.T) { testDeviceEmulatorTransition(t, false) } + +func BenchmarkParseLine(b *testing.B) { + list := `c *:* m +b *:* m +c 1:3 rwm +c 1:5 rwm +c 1:7 rwm +c 1:8 rwm +c 1:9 rwm +c 5:0 rwm +c 5:2 rwm +c 136:* rwm +c 10:200 rwm` + + var r *deviceRule + var err error + for i := 0; i < b.N; i++ { + s := bufio.NewScanner(strings.NewReader(list)) + for s.Scan() { + line := s.Text() + r, err = parseLine(line) + } + if err := s.Err(); err != nil { + b.Fatal(err) + } + } + b.Logf("rule: %v, err: %v", r, err) +}