Skip to content

Commit cfdcb39

Browse files
authored
Block AF_ALG in workspace seccomp profile (#21427)
1 parent 555bd83 commit cfdcb39

2 files changed

Lines changed: 69 additions & 6 deletions

File tree

components/ws-daemon/seccomp-profile-installer/main.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,36 @@ import (
88
"encoding/json"
99
"log"
1010
"os"
11+
"syscall"
1112

1213
"github.com/containerd/containerd/contrib/seccomp"
1314
"github.com/opencontainers/runtime-spec/specs-go"
1415
)
1516

16-
func main() {
17-
enc := json.NewEncoder(os.Stdout)
18-
enc.SetIndent("", " ")
19-
enc.SetEscapeHTML(false)
20-
17+
func defaultWorkspaceSeccompProfile(capabilities []string) *specs.LinuxSeccomp {
2118
spec := specs.Spec{
2219
Process: &specs.Process{
2320
Capabilities: &specs.LinuxCapabilities{
24-
Bounding: os.Args[1:],
21+
Bounding: capabilities,
2522
},
2623
},
2724
}
2825

2926
s := seccomp.DefaultProfile(&spec)
3027
s.Syscalls = append(s.Syscalls,
28+
// AF_ALG exposes the kernel crypto API via sockets. Blocking only this
29+
// family keeps regular networking intact while removing the copy.fail path.
30+
specs.LinuxSyscall{
31+
Names: []string{"socket"},
32+
Action: specs.ActErrno,
33+
Args: []specs.LinuxSeccompArg{
34+
{
35+
Index: 0,
36+
Value: syscall.AF_ALG,
37+
Op: specs.OpEqualTo,
38+
},
39+
},
40+
},
3141
specs.LinuxSyscall{
3242
Names: []string{
3343
"clone",
@@ -59,6 +69,16 @@ func main() {
5969
},
6070
)
6171

72+
return s
73+
}
74+
75+
func main() {
76+
enc := json.NewEncoder(os.Stdout)
77+
enc.SetIndent("", " ")
78+
enc.SetEscapeHTML(false)
79+
80+
s := defaultWorkspaceSeccompProfile(os.Args[1:])
81+
6282
err := enc.Encode(s)
6383
if err != nil {
6484
log.Fatalf("cannot marshal seccomp profile: %q", err)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
2+
// Licensed under the GNU Affero General Public License (AGPL).
3+
// See License.AGPL.txt in the project root for license information.
4+
5+
package main
6+
7+
import (
8+
"slices"
9+
"syscall"
10+
"testing"
11+
12+
"github.com/opencontainers/runtime-spec/specs-go"
13+
)
14+
15+
func TestDefaultWorkspaceSeccompProfileBlocksAFALGSocket(t *testing.T) {
16+
profile := defaultWorkspaceSeccompProfile([]string{"AUDIT_WRITE", "NET_BIND_SERVICE"})
17+
18+
for _, syscallRule := range profile.Syscalls {
19+
if !slices.Contains(syscallRule.Names, "socket") || syscallRule.Action != specs.ActErrno {
20+
continue
21+
}
22+
23+
for _, arg := range syscallRule.Args {
24+
if arg.Index == 0 && arg.Value == syscall.AF_ALG && arg.Op == specs.OpEqualTo {
25+
return
26+
}
27+
}
28+
}
29+
30+
t.Fatalf("expected seccomp profile to block socket(AF_ALG, ...)")
31+
}
32+
33+
func TestDefaultWorkspaceSeccompProfileKeepsRegularSocketsAvailable(t *testing.T) {
34+
profile := defaultWorkspaceSeccompProfile([]string{"AUDIT_WRITE", "NET_BIND_SERVICE"})
35+
36+
for _, syscallRule := range profile.Syscalls {
37+
if slices.Contains(syscallRule.Names, "socket") && syscallRule.Action == specs.ActAllow && len(syscallRule.Args) == 0 {
38+
return
39+
}
40+
}
41+
42+
t.Fatalf("expected seccomp profile to preserve generic socket allow rule")
43+
}

0 commit comments

Comments
 (0)