@@ -6,10 +6,17 @@ package daemon
66
77import (
88 "context"
9+ "path/filepath"
910
1011 "github.com/containerd/cgroups"
12+ "github.com/gitpod-io/gitpod/ws-daemon/pkg/container"
1113 "github.com/gitpod-io/gitpod/ws-daemon/pkg/dispatch"
14+ "github.com/opencontainers/runc/libcontainer/cgroups/ebpf"
15+ "github.com/opencontainers/runc/libcontainer/cgroups/ebpf/devicefilter"
16+ "github.com/opencontainers/runc/libcontainer/devices"
17+ "github.com/opencontainers/runc/libcontainer/specconv"
1218 "github.com/opencontainers/runtime-spec/specs-go"
19+ "golang.org/x/sys/unix"
1320 "golang.org/x/xerrors"
1421)
1522
@@ -18,24 +25,31 @@ var (
1825 fuseDeviceMinor int64 = 229
1926)
2027
21- type CgroupCustomizer struct {
28+ func NewCGroupCustomizer (basePath string , unified bool ) dispatch.Listener {
29+ if unified {
30+ return & CgroupCustomizerV2 {
31+ cgroupBasePath : basePath ,
32+ }
33+ } else {
34+ return & CgroupCustomizerV1 {
35+ cgroupBasePath : basePath ,
36+ }
37+ }
38+ }
39+
40+ type CgroupCustomizerV1 struct {
2241 cgroupBasePath string
2342}
2443
25- func (c * CgroupCustomizer ) WithCgroupBasePath (basePath string ) {
44+ func (c * CgroupCustomizerV1 ) WithCgroupBasePath (basePath string ) {
2645 c .cgroupBasePath = basePath
2746}
2847
2948// WorkspaceAdded will customize the cgroups for every workspace that is started
30- func (c * CgroupCustomizer ) WorkspaceAdded (ctx context.Context , ws * dispatch.Workspace ) error {
31- disp := dispatch .GetFromContext (ctx )
32- if disp == nil {
33- return xerrors .Errorf ("no dispatch available" )
34- }
35-
36- cgroupPath , err := disp .Runtime .ContainerCGroupPath (context .Background (), ws .ContainerID )
49+ func (c * CgroupCustomizerV1 ) WorkspaceAdded (ctx context.Context , ws * dispatch.Workspace ) error {
50+ cgroupPath , err := retrieveCGroupPath (ctx , ws .ContainerID )
3751 if err != nil {
38- return xerrors . Errorf ( "cannot start governer: %w" , err )
52+ return err
3953 }
4054
4155 control , err := cgroups .Load (c .customV1 , cgroups .StaticPath (cgroupPath ))
@@ -64,8 +78,72 @@ func (c *CgroupCustomizer) WorkspaceAdded(ctx context.Context, ws *dispatch.Work
6478 return nil
6579}
6680
67- func (c * CgroupCustomizer ) customV1 () ([]cgroups.Subsystem , error ) {
81+ func (c * CgroupCustomizerV1 ) customV1 () ([]cgroups.Subsystem , error ) {
6882 return []cgroups.Subsystem {
6983 cgroups .NewDevices (c .cgroupBasePath ),
7084 }, nil
7185}
86+
87+ type CgroupCustomizerV2 struct {
88+ cgroupBasePath string
89+ }
90+
91+ func (c * CgroupCustomizerV2 ) WorkspaceAdded (ctx context.Context , ws * dispatch.Workspace ) error {
92+ cgroupPath , err := retrieveCGroupPath (ctx , ws .ContainerID )
93+ if err != nil {
94+ return err
95+ }
96+
97+ fullCgroupPath := filepath .Join (c .cgroupBasePath , cgroupPath )
98+ cgroupFD , err := unix .Open (fullCgroupPath , unix .O_DIRECTORY | unix .O_RDONLY , 0o600 )
99+ if err != nil {
100+ return xerrors .Errorf ("cannot get directory fd for %s" , fullCgroupPath )
101+ }
102+ defer unix .Close (cgroupFD )
103+
104+ insts , license , err := devicefilter .DeviceFilter (composeDeviceRules ())
105+ if err != nil {
106+ return xerrors .Errorf ("failed to generate device filter: %w" , err )
107+ }
108+
109+ _ , err = ebpf .LoadAttachCgroupDeviceFilter (insts , license , cgroupFD )
110+ return err
111+ }
112+
113+ func retrieveCGroupPath (ctx context.Context , id container.ID ) (string , error ) {
114+ disp := dispatch .GetFromContext (ctx )
115+ if disp == nil {
116+ return "" , xerrors .Errorf ("no dispatch available" )
117+ }
118+
119+ cgroupPath , err := disp .Runtime .ContainerCGroupPath (context .Background (), id )
120+ if err != nil {
121+ return "" , xerrors .Errorf ("cannot retrieve cgroup path: %w" , err )
122+ }
123+
124+ return cgroupPath , nil
125+ }
126+
127+ func composeDeviceRules () []* devices.Rule {
128+ denyAll := devices.Rule {
129+ Type : 'a' ,
130+ Permissions : "rwm" ,
131+ Allow : false ,
132+ }
133+
134+ allowFuse := devices.Rule {
135+ Type : 'c' ,
136+ Major : fuseDeviceMajor ,
137+ Minor : fuseDeviceMinor ,
138+ Permissions : "rwm" ,
139+ Allow : true ,
140+ }
141+
142+ deviceRules := make ([]* devices.Rule , 0 )
143+ deviceRules = append (deviceRules , & denyAll , & allowFuse )
144+ for _ , device := range specconv .AllowedDevices {
145+ deviceRules = append (deviceRules , & device .Rule )
146+ }
147+
148+ return deviceRules
149+ }
0 commit comments