Skip to content

Commit 483aa62

Browse files
committed
daemon: load and cache sysInfo on initialization
The `daemon.RawSysInfo()` function can be a heavy operation, as it collects information about all cgroups on the host, networking, AppArmor, Seccomp, etc. While looking at our code, I noticed that various parts in the code call this function, potentially even _multiple times_ per container, for example, it is called from: - `verifyPlatformContainerSettings()` - `oci.WithCgroups()` if the daemon has `cpu-rt-period` or `cpu-rt-runtime` configured - in `ContainerDecoder.DecodeConfig()`, which is called on boith `container create` and `container commit` Given that this information is not expected to change during the daemon's lifecycle, and various information coming from this (such as seccomp and apparmor status) was already cached, we may as well load it once, and cache the results in the daemon instance. This patch updates `daemon.RawSysInfo()` to use a `sync.Once()` so that it's only executed once for the daemon's lifecycle. Signed-off-by: Sebastiaan van Stijn <[email protected]>
1 parent f045d0d commit 483aa62

7 files changed

Lines changed: 42 additions & 34 deletions

File tree

daemon/container_linux.go

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,18 @@ import (
1111
func (daemon *Daemon) saveAppArmorConfig(container *container.Container) error {
1212
container.AppArmorProfile = "" // we don't care about the previous value.
1313

14-
if !daemon.apparmorEnabled {
14+
if !daemon.RawSysInfo().AppArmor {
1515
return nil // if apparmor is disabled there is nothing to do here.
1616
}
1717

1818
if err := parseSecurityOpt(container, container.HostConfig); err != nil {
1919
return errdefs.InvalidParameter(err)
2020
}
2121

22-
if !container.HostConfig.Privileged {
23-
if container.AppArmorProfile == "" {
24-
container.AppArmorProfile = defaultAppArmorProfile
25-
}
26-
27-
} else {
22+
if container.HostConfig.Privileged {
2823
container.AppArmorProfile = unconfinedAppArmorProfile
24+
} else if container.AppArmorProfile == "" {
25+
container.AppArmorProfile = defaultAppArmorProfile
2926
}
3027
return nil
3128
}

daemon/daemon.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import (
4747
"github.com/docker/docker/pkg/fileutils"
4848
"github.com/docker/docker/pkg/idtools"
4949
"github.com/docker/docker/pkg/plugingetter"
50+
"github.com/docker/docker/pkg/sysinfo"
5051
"github.com/docker/docker/pkg/system"
5152
"github.com/docker/docker/pkg/truncindex"
5253
"github.com/docker/docker/plugin"
@@ -92,8 +93,8 @@ type Daemon struct {
9293
netController libnetwork.NetworkController
9394
volumes *volumesservice.VolumesService
9495
root string
95-
seccompEnabled bool
96-
apparmorEnabled bool
96+
sysInfoOnce sync.Once
97+
sysInfo *sysinfo.SysInfo
9798
shutdown bool
9899
idMapping *idtools.IdentityMapping
99100
graphDriver string // TODO: move graphDriver field to an InfoService
@@ -1034,8 +1035,6 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
10341035
d.EventsService = events.New()
10351036
d.root = config.Root
10361037
d.idMapping = idMapping
1037-
d.seccompEnabled = sysInfo.Seccomp
1038-
d.apparmorEnabled = sysInfo.AppArmor
10391038

10401039
d.linkIndex = newLinkIndex()
10411040

@@ -1472,3 +1471,16 @@ func (daemon *Daemon) BuilderBackend() builder.Backend {
14721471
*images.ImageService
14731472
}{daemon, daemon.imageService}
14741473
}
1474+
1475+
// RawSysInfo returns *sysinfo.SysInfo .
1476+
func (daemon *Daemon) RawSysInfo() *sysinfo.SysInfo {
1477+
daemon.sysInfoOnce.Do(func() {
1478+
// We check if sysInfo is not set here, to allow some test to
1479+
// override the actual sysInfo.
1480+
if daemon.sysInfo == nil {
1481+
daemon.loadSysInfo()
1482+
}
1483+
})
1484+
1485+
return daemon.sysInfo
1486+
}

daemon/daemon_unix.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,19 +1731,14 @@ func (daemon *Daemon) setupSeccompProfile() error {
17311731
return nil
17321732
}
17331733

1734-
// RawSysInfo returns *sysinfo.SysInfo .
1735-
func (daemon *Daemon) RawSysInfo() *sysinfo.SysInfo {
1734+
func (daemon *Daemon) loadSysInfo() {
17361735
var siOpts []sysinfo.Opt
17371736
if daemon.getCgroupDriver() == cgroupSystemdDriver {
17381737
if euid := os.Getenv("ROOTLESSKIT_PARENT_EUID"); euid != "" {
17391738
siOpts = append(siOpts, sysinfo.WithCgroup2GroupPath("/user.slice/user-"+euid+".slice"))
17401739
}
17411740
}
1742-
return sysinfo.New(siOpts...)
1743-
}
1744-
1745-
func recursiveUnmount(target string) error {
1746-
return mount.RecursiveUnmount(target)
1741+
daemon.sysInfo = sysinfo.New(siOpts...)
17471742
}
17481743

17491744
func (daemon *Daemon) initLibcontainerd(ctx context.Context) error {
@@ -1757,3 +1752,7 @@ func (daemon *Daemon) initLibcontainerd(ctx context.Context) error {
17571752
)
17581753
return err
17591754
}
1755+
1756+
func recursiveUnmount(target string) error {
1757+
return mount.RecursiveUnmount(target)
1758+
}

daemon/daemon_unsupported.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ const platformSupported = false
1313
func setupResolvConf(config *config.Config) {
1414
}
1515

16-
// RawSysInfo returns *sysinfo.SysInfo .
17-
func (daemon *Daemon) RawSysInfo() *sysinfo.SysInfo {
18-
return sysinfo.New()
16+
func (daemon *Daemon) loadSysInfo() {
17+
daemon.sysInfo = sysinfo.New()
1918
}

daemon/daemon_windows.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -650,9 +650,8 @@ func (daemon *Daemon) initRuntimes(_ map[string]types.Runtime) error {
650650
func setupResolvConf(config *config.Config) {
651651
}
652652

653-
// RawSysInfo returns *sysinfo.SysInfo .
654-
func (daemon *Daemon) RawSysInfo() *sysinfo.SysInfo {
655-
return sysinfo.New()
653+
func (daemon *Daemon) loadSysInfo() {
654+
daemon.sysInfo = sysinfo.New()
656655
}
657656

658657
func (daemon *Daemon) initLibcontainerd(ctx context.Context) error {

daemon/seccomp_linux.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func WithSeccomp(daemon *Daemon, c *container.Container) coci.SpecOpts {
2626
if c.HostConfig.Privileged {
2727
return nil
2828
}
29-
if !daemon.seccompEnabled {
29+
if !daemon.RawSysInfo().Seccomp {
3030
if c.SeccompProfile != "" && c.SeccompProfile != dconfig.SeccompProfileDefault {
3131
return fmt.Errorf("seccomp is not enabled in your kernel, cannot run a custom seccomp profile")
3232
}

daemon/seccomp_linux_test.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/docker/docker/container"
1212
dconfig "github.com/docker/docker/daemon/config"
1313
doci "github.com/docker/docker/oci"
14+
"github.com/docker/docker/pkg/sysinfo"
1415
"github.com/docker/docker/profiles/seccomp"
1516
specs "github.com/opencontainers/runtime-spec/specs-go"
1617
"gotest.tools/v3/assert"
@@ -31,7 +32,7 @@ func TestWithSeccomp(t *testing.T) {
3132
{
3233
comment: "unconfined seccompProfile runs unconfined",
3334
daemon: &Daemon{
34-
seccompEnabled: true,
35+
sysInfo: &sysinfo.SysInfo{Seccomp: true},
3536
},
3637
c: &container.Container{
3738
SeccompProfile: dconfig.SeccompProfileUnconfined,
@@ -45,7 +46,7 @@ func TestWithSeccomp(t *testing.T) {
4546
{
4647
comment: "privileged container w/ custom profile runs unconfined",
4748
daemon: &Daemon{
48-
seccompEnabled: true,
49+
sysInfo: &sysinfo.SysInfo{Seccomp: true},
4950
},
5051
c: &container.Container{
5152
SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_LOG\" }",
@@ -59,7 +60,7 @@ func TestWithSeccomp(t *testing.T) {
5960
{
6061
comment: "privileged container w/ default runs unconfined",
6162
daemon: &Daemon{
62-
seccompEnabled: true,
63+
sysInfo: &sysinfo.SysInfo{Seccomp: true},
6364
},
6465
c: &container.Container{
6566
SeccompProfile: "",
@@ -73,7 +74,7 @@ func TestWithSeccomp(t *testing.T) {
7374
{
7475
comment: "privileged container w/ daemon profile runs unconfined",
7576
daemon: &Daemon{
76-
seccompEnabled: true,
77+
sysInfo: &sysinfo.SysInfo{Seccomp: true},
7778
seccompProfile: []byte("{ \"defaultAction\": \"SCMP_ACT_ERRNO\" }"),
7879
},
7980
c: &container.Container{
@@ -88,7 +89,7 @@ func TestWithSeccomp(t *testing.T) {
8889
{
8990
comment: "custom profile when seccomp is disabled returns error",
9091
daemon: &Daemon{
91-
seccompEnabled: false,
92+
sysInfo: &sysinfo.SysInfo{Seccomp: false},
9293
},
9394
c: &container.Container{
9495
SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_ERRNO\" }",
@@ -103,7 +104,7 @@ func TestWithSeccomp(t *testing.T) {
103104
{
104105
comment: "empty profile name loads default profile",
105106
daemon: &Daemon{
106-
seccompEnabled: true,
107+
sysInfo: &sysinfo.SysInfo{Seccomp: true},
107108
},
108109
c: &container.Container{
109110
SeccompProfile: "",
@@ -122,7 +123,7 @@ func TestWithSeccomp(t *testing.T) {
122123
{
123124
comment: "load container's profile",
124125
daemon: &Daemon{
125-
seccompEnabled: true,
126+
sysInfo: &sysinfo.SysInfo{Seccomp: true},
126127
},
127128
c: &container.Container{
128129
SeccompProfile: "{ \"defaultAction\": \"SCMP_ACT_ERRNO\" }",
@@ -143,7 +144,7 @@ func TestWithSeccomp(t *testing.T) {
143144
{
144145
comment: "load daemon's profile",
145146
daemon: &Daemon{
146-
seccompEnabled: true,
147+
sysInfo: &sysinfo.SysInfo{Seccomp: true},
147148
seccompProfile: []byte("{ \"defaultAction\": \"SCMP_ACT_ERRNO\" }"),
148149
},
149150
c: &container.Container{
@@ -165,7 +166,7 @@ func TestWithSeccomp(t *testing.T) {
165166
{
166167
comment: "load prioritise container profile over daemon's",
167168
daemon: &Daemon{
168-
seccompEnabled: true,
169+
sysInfo: &sysinfo.SysInfo{Seccomp: true},
169170
seccompProfile: []byte("{ \"defaultAction\": \"SCMP_ACT_ERRNO\" }"),
170171
},
171172
c: &container.Container{
@@ -185,6 +186,7 @@ func TestWithSeccomp(t *testing.T) {
185186
}(),
186187
},
187188
} {
189+
x := x
188190
t.Run(x.comment, func(t *testing.T) {
189191
opts := WithSeccomp(x.daemon, x.c)
190192
err := opts(nil, nil, nil, &x.inSpec)

0 commit comments

Comments
 (0)