@@ -40,6 +40,8 @@ var generateFlags = []cli.Flag{
4040 cli.StringSliceFlag {Name : "linux-device-add" , Usage : "add a device which must be made available in the container" },
4141 cli.StringSliceFlag {Name : "linux-device-remove" , Usage : "remove a device which must be made available in the container" },
4242 cli.BoolFlag {Name : "linux-device-remove-all" , Usage : "remove all devices which must be made available in the container" },
43+ cli.StringSliceFlag {Name : "linux-device-cgroup-add" , Usage : "add a device access rule" },
44+ cli.StringSliceFlag {Name : "linux-device-cgroup-remove" , Usage : "remove a device access rule" },
4345 cli.BoolFlag {Name : "linux-disable-oom-kill" , Usage : "disable OOM Killer" },
4446 cli.StringSliceFlag {Name : "linux-gidmappings" , Usage : "add GIDMappings e.g HostID:ContainerID:Size" },
4547 cli.StringSliceFlag {Name : "linux-hugepage-limits-add" , Usage : "add hugepage resource limits" },
@@ -249,6 +251,28 @@ func setupSpec(g *generate.Generator, context *cli.Context) error {
249251 }
250252 }
251253
254+ if context .IsSet ("linux-device-cgroup-add" ) {
255+ devices := context .StringSlice ("linux-device-cgroup-add" )
256+ for _ , device := range devices {
257+ dev , err := parseLinuxResourcesDeviceAccess (device , g )
258+ if err != nil {
259+ return err
260+ }
261+ g .AddLinuxResourcesDevice (dev .Allow , dev .Type , dev .Major , dev .Minor , dev .Access )
262+ }
263+ }
264+
265+ if context .IsSet ("linux-device-cgroup-remove" ) {
266+ devices := context .StringSlice ("linux-device-cgroup-remove" )
267+ for _ , device := range devices {
268+ dev , err := parseLinuxResourcesDeviceAccess (device , g )
269+ if err != nil {
270+ return err
271+ }
272+ g .RemoveLinuxResourcesDevice (dev .Allow , dev .Type , dev .Major , dev .Minor , dev .Access )
273+ }
274+ }
275+
252276 if context .IsSet ("linux-readonly-paths" ) {
253277 paths := context .StringSlice ("linux-readonly-paths" )
254278 for _ , path := range paths {
@@ -986,6 +1010,82 @@ func parseDevice(device string, g *generate.Generator) (rspec.LinuxDevice, error
9861010 return dev , nil
9871011}
9881012
1013+ var cgroupDeviceType = map [string ]bool {
1014+ "a" : true , // all
1015+ "b" : true , // block device
1016+ "c" : true , // character device
1017+ }
1018+ var cgroupDeviceAccess = map [string ]bool {
1019+ "r" : true , //read
1020+ "w" : true , //write
1021+ "m" : true , //mknod
1022+ }
1023+
1024+ // parseLinuxResourcesDeviceAccess parses the raw string passed with the --device-access-add flag
1025+ func parseLinuxResourcesDeviceAccess (device string , g * generate.Generator ) (rspec.LinuxDeviceCgroup , error ) {
1026+ var allow bool
1027+ var devType , access string
1028+ var major , minor * int64
1029+
1030+ argsParts := strings .Split (device , "," )
1031+
1032+ switch argsParts [0 ] {
1033+ case "allow" :
1034+ allow = true
1035+ case "deny" :
1036+ allow = false
1037+ default :
1038+ return rspec.LinuxDeviceCgroup {},
1039+ fmt .Errorf ("Only 'allow' and 'deny' are allowed in the first field of device-access-add: %s" , device )
1040+ }
1041+
1042+ for _ , s := range argsParts [1 :] {
1043+ s = strings .TrimSpace (s )
1044+ if s == "" {
1045+ continue
1046+ }
1047+ parts := strings .SplitN (s , "=" , 2 )
1048+ if len (parts ) != 2 {
1049+ return rspec.LinuxDeviceCgroup {}, fmt .Errorf ("Incomplete device-access-add arguments: %s" , s )
1050+ }
1051+ name , value := parts [0 ], parts [1 ]
1052+
1053+ switch name {
1054+ case "type" :
1055+ if ! cgroupDeviceType [value ] {
1056+ return rspec.LinuxDeviceCgroup {}, fmt .Errorf ("Invalid device type in device-access-add: %s" , value )
1057+ }
1058+ devType = value
1059+ case "major" :
1060+ i , err := strconv .ParseInt (value , 10 , 64 )
1061+ if err != nil {
1062+ return rspec.LinuxDeviceCgroup {}, err
1063+ }
1064+ major = & i
1065+ case "minor" :
1066+ i , err := strconv .ParseInt (value , 10 , 64 )
1067+ if err != nil {
1068+ return rspec.LinuxDeviceCgroup {}, err
1069+ }
1070+ minor = & i
1071+ case "access" :
1072+ for _ , c := range strings .Split (value , "" ) {
1073+ if ! cgroupDeviceAccess [c ] {
1074+ return rspec.LinuxDeviceCgroup {}, fmt .Errorf ("Invalid device access in device-access-add: %s" , c )
1075+ }
1076+ }
1077+ access = value
1078+ }
1079+ }
1080+ return rspec.LinuxDeviceCgroup {
1081+ Allow : allow ,
1082+ Type : devType ,
1083+ Major : major ,
1084+ Minor : minor ,
1085+ Access : access ,
1086+ }, nil
1087+ }
1088+
9891089func addSeccomp (context * cli.Context , g * generate.Generator ) error {
9901090
9911091 // Set the DefaultAction of seccomp
0 commit comments