@@ -40,6 +40,8 @@ var generateFlags = []cli.Flag{
40
40
cli.StringSliceFlag {Name : "linux-device-add" , Usage : "add a device which must be made available in the container" },
41
41
cli.StringSliceFlag {Name : "linux-device-remove" , Usage : "remove a device which must be made available in the container" },
42
42
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" },
43
45
cli.BoolFlag {Name : "linux-disable-oom-kill" , Usage : "disable OOM Killer" },
44
46
cli.StringSliceFlag {Name : "linux-gidmappings" , Usage : "add GIDMappings e.g HostID:ContainerID:Size" },
45
47
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 {
249
251
}
250
252
}
251
253
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
+
252
276
if context .IsSet ("linux-readonly-paths" ) {
253
277
paths := context .StringSlice ("linux-readonly-paths" )
254
278
for _ , path := range paths {
@@ -986,6 +1010,82 @@ func parseDevice(device string, g *generate.Generator) (rspec.LinuxDevice, error
986
1010
return dev , nil
987
1011
}
988
1012
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
+
989
1089
func addSeccomp (context * cli.Context , g * generate.Generator ) error {
990
1090
991
1091
// Set the DefaultAction of seccomp
0 commit comments