Skip to content

Commit 9ec2778

Browse files
authored
Merge pull request #4467 from cyphar/apparmor-update-profile
apparmor: handle signal mediation
2 parents 6d68490 + d8572b6 commit 9ec2778

2 files changed

Lines changed: 60 additions & 4 deletions

File tree

contrib/apparmor/template.go

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// +build linux
22

33
/*
4+
Copyright The docker Authors.
5+
Copyright The Moby Authors.
46
Copyright The containerd Authors.
57
68
Licensed under the Apache License, Version 2.0 (the "License");
@@ -22,6 +24,7 @@ import (
2224
"bufio"
2325
"fmt"
2426
"io"
27+
"io/ioutil"
2528
"os"
2629
"os/exec"
2730
"path"
@@ -32,6 +35,10 @@ import (
3235
"github.com/pkg/errors"
3336
)
3437

38+
// NOTE: This code is copied from <github.com/docker/docker/profiles/apparmor>.
39+
// If you plan to make any changes, please make sure they are also sent
40+
// upstream.
41+
3542
const dir = "/etc/apparmor.d"
3643

3744
const defaultTemplate = `
@@ -48,6 +55,14 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
4855
capability,
4956
file,
5057
umount,
58+
{{if ge .Version 208096}}
59+
# Host (privileged) processes may send signals to container processes.
60+
signal (receive) peer=unconfined,
61+
# Manager may send signals to container processes.
62+
signal (receive) peer={{.DaemonProfile}},
63+
# Container processes may send signals amongst themselves.
64+
signal (send,receive) peer={{.Name}},
65+
{{end}}
5166
5267
deny @{PROC}/* w, # deny write for all files directly in /proc (not in a subdir)
5368
# deny write to files not in /proc/<number>/** or /proc/sys/**
@@ -76,10 +91,23 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
7691
`
7792

7893
type data struct {
79-
Name string
80-
Imports []string
81-
InnerImports []string
82-
Version int
94+
Name string
95+
Imports []string
96+
InnerImports []string
97+
DaemonProfile string
98+
Version int
99+
}
100+
101+
func cleanProfileName(profile string) string {
102+
// Normally profiles are suffixed by " (enforce)". AppArmor profiles cannot
103+
// contain spaces so this doesn't restrict daemon profile names.
104+
if parts := strings.SplitN(profile, " ", 2); len(parts) >= 1 {
105+
profile = parts[0]
106+
}
107+
if profile == "" {
108+
profile = "unconfined"
109+
}
110+
return profile
83111
}
84112

85113
func loadData(name string) (*data, error) {
@@ -100,6 +128,16 @@ func loadData(name string) (*data, error) {
100128
return nil, errors.Wrap(err, "get apparmor_parser version")
101129
}
102130
p.Version = ver
131+
132+
// Figure out the daemon profile.
133+
currentProfile, err := ioutil.ReadFile("/proc/self/attr/current")
134+
if err != nil {
135+
// If we couldn't get the daemon profile, assume we are running
136+
// unconfined which is generally the default.
137+
currentProfile = nil
138+
}
139+
p.DaemonProfile = cleanProfileName(string(currentProfile))
140+
103141
return &p, nil
104142
}
105143

contrib/apparmor/template_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// +build linux
2+
3+
package apparmor
4+
5+
import (
6+
"testing"
7+
8+
"gotest.tools/v3/assert"
9+
)
10+
11+
func TestCleanProfileName(t *testing.T) {
12+
assert.Equal(t, cleanProfileName(""), "unconfined")
13+
assert.Equal(t, cleanProfileName("unconfined"), "unconfined")
14+
assert.Equal(t, cleanProfileName("unconfined (enforce)"), "unconfined")
15+
assert.Equal(t, cleanProfileName("docker-default"), "docker-default")
16+
assert.Equal(t, cleanProfileName("foo"), "foo")
17+
assert.Equal(t, cleanProfileName("foo (enforce)"), "foo")
18+
}

0 commit comments

Comments
 (0)