@@ -6,10 +6,17 @@ package daemon
6
6
7
7
import (
8
8
"context"
9
+ "path/filepath"
9
10
10
11
"github.com/containerd/cgroups"
12
+ "github.com/gitpod-io/gitpod/ws-daemon/pkg/container"
11
13
"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"
12
18
"github.com/opencontainers/runtime-spec/specs-go"
19
+ "golang.org/x/sys/unix"
13
20
"golang.org/x/xerrors"
14
21
)
15
22
@@ -18,24 +25,31 @@ var (
18
25
fuseDeviceMinor int64 = 229
19
26
)
20
27
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 {
22
41
cgroupBasePath string
23
42
}
24
43
25
- func (c * CgroupCustomizer ) WithCgroupBasePath (basePath string ) {
44
+ func (c * CgroupCustomizerV1 ) WithCgroupBasePath (basePath string ) {
26
45
c .cgroupBasePath = basePath
27
46
}
28
47
29
48
// 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 )
37
51
if err != nil {
38
- return xerrors . Errorf ( "cannot start governer: %w" , err )
52
+ return err
39
53
}
40
54
41
55
control , err := cgroups .Load (c .customV1 , cgroups .StaticPath (cgroupPath ))
@@ -64,8 +78,72 @@ func (c *CgroupCustomizer) WorkspaceAdded(ctx context.Context, ws *dispatch.Work
64
78
return nil
65
79
}
66
80
67
- func (c * CgroupCustomizer ) customV1 () ([]cgroups.Subsystem , error ) {
81
+ func (c * CgroupCustomizerV1 ) customV1 () ([]cgroups.Subsystem , error ) {
68
82
return []cgroups.Subsystem {
69
83
cgroups .NewDevices (c .cgroupBasePath ),
70
84
}, nil
71
85
}
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