@@ -17,7 +17,7 @@ import (
1717
1818// systemdProperties takes the configured device rules and generates a
1919// corresponding set of systemd properties to configure the devices correctly.
20- func systemdProperties (r * configs.Resources , sdVer int ) ([]systemdDbus.Property , error ) {
20+ func systemdProperties (r * configs.Resources , sdVer int , cgroupVer int ) ([]systemdDbus.Property , error ) {
2121 if r .SkipDevices {
2222 return nil , nil
2323 }
@@ -95,12 +95,33 @@ func systemdProperties(r *configs.Resources, sdVer int) ([]systemdDbus.Property,
9595 // The only type of rule we can't handle is wildcard-major rules, and
9696 // so we'll give a warning in that case (note that the fallback code
9797 // will insert any rules systemd couldn't handle). What amazing fun.
98+ //
99+ // The rules generated here are applied by systemd, and then runc applies
100+ // its own rules on top of those. If some rules can not be converted to
101+ // systemd properties, there will be two different sets of rules, and
102+ // the end result depends on cgroup version:
103+ //
104+ // * In cgroup v1 ("device.{allow,deny}" files), the rules set by systemd
105+ // gets overwritten by runc, meaning the correct rules are in effect.
106+ // Therefore, a warning is sufficient here (except for the case when
107+ // systemd is restarted and our rules gets overwritten, but there
108+ // is nothing we can do here).
109+ //
110+ // * In cgroup v2 (ebpf), both systemd and runc ebpf programs are loaded,
111+ // and the device access is granted only if both programs return "allow".
112+ // Therefore, the rules that can not be translated to systemd properties
113+ // won't work, so we must return an error.
98114
99115 if rule .Major == devices .Wildcard {
100116 // "_ *:n _" rules aren't supported by systemd.
101117 if rule .Minor != devices .Wildcard {
102- logrus .Warnf ("systemd doesn't support '*:n' device rules -- temporarily ignoring rule: %v" , * rule )
118+ w := fmt .Errorf ("systemd does not support wildcard-major device rule: %+v" , * rule )
119+ if cgroupVer == 2 {
120+ return nil , w
121+ }
122+ logrus .Warnf ("temporarily ignoring rule: %v" , w )
103123 continue
124+
104125 }
105126
106127 // "_ *:* _" rules just wildcard everything.
@@ -117,7 +138,11 @@ func systemdProperties(r *configs.Resources, sdVer int) ([]systemdDbus.Property,
117138 }
118139 if group == "" {
119140 // Couldn't find a group.
120- logrus .Warnf ("could not find device group for '%v/%d' in /proc/devices -- temporarily ignoring rule: %v" , rule .Type , rule .Major , * rule )
141+ w := fmt .Errorf ("systemd older than v240 does not support wildcard-minor rules for devices not listed in /proc/devices: +%v" , * rule )
142+ if cgroupVer == 2 {
143+ return nil , err
144+ }
145+ logrus .Warnf ("temporarily ignoring rule: %v" , w )
121146 continue
122147 }
123148 entry .Path = group
@@ -131,12 +156,13 @@ func systemdProperties(r *configs.Resources, sdVer int) ([]systemdDbus.Property,
131156 }
132157 if sdVer < 240 {
133158 // Old systemd versions use stat(2) on path to find out device major:minor
134- // numbers and type. If the path doesn't exist, it will not add the rule,
135- // emitting a warning instead.
136- // Since all of this logic is best-effort anyway (we manually set these
137- // rules separately to systemd) we can safely skip entries that don't
138- // have a corresponding path.
159+ // numbers and type. If the path doesn't exist, it will not add the rule.
139160 if _ , err := os .Stat (entry .Path ); err != nil {
161+ w := fmt .Errorf ("systemd older than v240 does not support device rules for non-existing device: %v" , err )
162+ if cgroupVer == 2 {
163+ return nil , err
164+ }
165+ logrus .Warnf ("temporarily ignoring rule: %v" , w )
140166 continue
141167 }
142168 }
0 commit comments