...
1 package fs
2
3 import (
4 "bytes"
5 "errors"
6 "reflect"
7
8 "github.com/opencontainers/runc/libcontainer/cgroups"
9 cgroupdevices "github.com/opencontainers/runc/libcontainer/cgroups/devices"
10 "github.com/opencontainers/runc/libcontainer/configs"
11 "github.com/opencontainers/runc/libcontainer/devices"
12 "github.com/opencontainers/runc/libcontainer/userns"
13 )
14
15 type DevicesGroup struct {
16 TestingSkipFinalCheck bool
17 }
18
19 func (s *DevicesGroup) Name() string {
20 return "devices"
21 }
22
23 func (s *DevicesGroup) Apply(path string, r *configs.Resources, pid int) error {
24 if r.SkipDevices {
25 return nil
26 }
27 if path == "" {
28
29
30 return errSubsystemDoesNotExist
31 }
32
33 return apply(path, pid)
34 }
35
36 func loadEmulator(path string) (*cgroupdevices.Emulator, error) {
37 list, err := cgroups.ReadFile(path, "devices.list")
38 if err != nil {
39 return nil, err
40 }
41 return cgroupdevices.EmulatorFromList(bytes.NewBufferString(list))
42 }
43
44 func buildEmulator(rules []*devices.Rule) (*cgroupdevices.Emulator, error) {
45
46 emu := &cgroupdevices.Emulator{}
47 for _, rule := range rules {
48 if err := emu.Apply(*rule); err != nil {
49 return nil, err
50 }
51 }
52 return emu, nil
53 }
54
55 func (s *DevicesGroup) Set(path string, r *configs.Resources) error {
56 if userns.RunningInUserNS() || r.SkipDevices {
57 return nil
58 }
59
60
61
62 current, err := loadEmulator(path)
63 if err != nil {
64 return err
65 }
66 target, err := buildEmulator(r.Devices)
67 if err != nil {
68 return err
69 }
70
71
72
73 transitionRules, err := current.Transition(target)
74 if err != nil {
75 return err
76 }
77 for _, rule := range transitionRules {
78 file := "devices.deny"
79 if rule.Allow {
80 file = "devices.allow"
81 }
82 if err := cgroups.WriteFile(path, file, rule.CgroupString()); err != nil {
83 return err
84 }
85 }
86
87
88
89
90
91
92
93 if !s.TestingSkipFinalCheck {
94 currentAfter, err := loadEmulator(path)
95 if err != nil {
96 return err
97 }
98 if !target.IsBlacklist() && !reflect.DeepEqual(currentAfter, target) {
99 return errors.New("resulting devices cgroup doesn't precisely match target")
100 } else if target.IsBlacklist() != currentAfter.IsBlacklist() {
101 return errors.New("resulting devices cgroup doesn't match target mode")
102 }
103 }
104 return nil
105 }
106
107 func (s *DevicesGroup) GetStats(path string, stats *cgroups.Stats) error {
108 return nil
109 }
110
View as plain text