@@ -63,6 +63,8 @@ var generateFlags = []cli.Flag{
6363 cli.StringSliceFlag {Name : "linux-readonly-paths" , Usage : "specifies paths readonly inside container" },
6464 cli.Int64Flag {Name : "linux-realtime-period" , Usage : "CPU period to be used for realtime scheduling (in usecs)" },
6565 cli.Int64Flag {Name : "linux-realtime-runtime" , Usage : "the time realtime scheduling may use (in usecs)" },
66+ cli.StringSliceFlag {Name : "linux-resources-device-add" , Usage : "add a device access rule" },
67+ cli.StringSliceFlag {Name : "linux-resources-device-remove" , Usage : "remove a device access rule" },
6668 cli.StringFlag {Name : "linux-rootfs-propagation" , Usage : "mount propagation for rootfs" },
6769 cli.StringFlag {Name : "linux-seccomp-allow" , Usage : "specifies syscalls to respond with allow" },
6870 cli.StringFlag {Name : "linux-seccomp-arch" , Usage : "specifies additional architectures permitted to be used for system calls" },
@@ -241,6 +243,28 @@ func setupSpec(g *generate.Generator, context *cli.Context) error {
241243 }
242244 }
243245
246+ if context .IsSet ("linux-resources-device-add" ) {
247+ devices := context .StringSlice ("linux-resources-device-add" )
248+ for _ , device := range devices {
249+ dev , err := parseLinuxResourcesDeviceAccess (device , g )
250+ if err != nil {
251+ return err
252+ }
253+ g .AddLinuxResourcesDevice (dev .Allow , dev .Type , dev .Major , dev .Minor , dev .Access )
254+ }
255+ }
256+
257+ if context .IsSet ("linux-resources-device-remove" ) {
258+ devices := context .StringSlice ("linux-resources-device-remove" )
259+ for _ , device := range devices {
260+ dev , err := parseLinuxResourcesDeviceAccess (device , g )
261+ if err != nil {
262+ return err
263+ }
264+ g .RemoveLinuxResourcesDevice (dev .Allow , dev .Type , dev .Major , dev .Minor , dev .Access )
265+ }
266+ }
267+
244268 if context .IsSet ("linux-readonly-paths" ) {
245269 paths := context .StringSlice ("linux-readonly-paths" )
246270 for _ , path := range paths {
@@ -811,6 +835,7 @@ func parseRlimit(rlimit string) (string, uint64, uint64, error) {
811835 return parts [0 ], uint64 (hard ), uint64 (soft ), nil
812836}
813837
838+ << << << < 9e0 e42dbf918070406a2a4a2e1476e7350ba9129
814839func parseNamespace (ns string ) (string , string , error ) {
815840 parts := strings .SplitN (ns , ":" , 2 )
816841 if len (parts ) == 0 || parts [0 ] == "" {
@@ -906,6 +931,82 @@ func parseDevice(device string, g *generate.Generator) (rspec.LinuxDevice, error
906931 return dev , nil
907932}
908933
934+ var cgroupDeviceType = map [string ]bool {
935+ "a" : true , // all
936+ "b" : true , // block device
937+ "c" : true , // character device
938+ }
939+ var cgroupDeviceAccess = map [string ]bool {
940+ "r" : true , //read
941+ "w" : true , //write
942+ "m" : true , //mknod
943+ }
944+
945+ // parseLinuxResourcesDeviceAccess parses the raw string passed with the --device-access-add flag
946+ func parseLinuxResourcesDeviceAccess (device string , g * generate.Generator ) (rspec.DeviceCgroup , error ) {
947+ var allow bool
948+ var devType , access string
949+ var major , minor * int64
950+
951+ argsParts := strings .Split (device , "," )
952+
953+ switch argsParts [0 ] {
954+ case "allow" :
955+ allow = true
956+ case "deny" :
957+ allow = false
958+ default :
959+ return rspec.DeviceCgroup {},
960+ fmt .Errorf ("Only 'allow' and 'deny' are allowed in the first field of device-access-add: %s" , device )
961+ }
962+
963+ for _ , s := range argsParts [1 :] {
964+ s = strings .TrimSpace (s )
965+ if s == "" {
966+ continue
967+ }
968+ parts := strings .SplitN (s , "=" , 2 )
969+ if len (parts ) != 2 {
970+ return rspec.DeviceCgroup {}, fmt .Errorf ("Incomplete device-access-add arguments: %s" , s )
971+ }
972+ name , value := parts [0 ], parts [1 ]
973+
974+ switch name {
975+ case "type" :
976+ if ! cgroupDeviceType [value ] {
977+ return rspec.DeviceCgroup {}, fmt .Errorf ("Invalid device type in device-access-add: %s" , value )
978+ }
979+ devType = & value
980+ case "major" :
981+ i , err := strconv .ParseInt (value , 10 , 64 )
982+ if err != nil {
983+ return rspec.DeviceCgroup {}, err
984+ }
985+ major = & i
986+ case "minor" :
987+ i , err := strconv .ParseInt (value , 10 , 64 )
988+ if err != nil {
989+ return rspec.DeviceCgroup {}, err
990+ }
991+ minor = & i
992+ case "access" :
993+ for _ , c := range strings .Split (value , "" ) {
994+ if ! cgroupDeviceAccess [c ] {
995+ return rspec.DeviceCgroup {}, fmt .Errorf ("Invalid device access in device-access-add: %s" , c )
996+ }
997+ }
998+ access = & value
999+ }
1000+ }
1001+ return rspec.DeviceCgroup {
1002+ Allow : allow ,
1003+ Type : devType ,
1004+ Major : major ,
1005+ Minor : minor ,
1006+ Access : access ,
1007+ }, nil
1008+ }
1009+
9091010func addSeccomp (context * cli.Context , g * generate.Generator ) error {
9101011
9111012 // Set the DefaultAction of seccomp
0 commit comments