8000 Prefer loading `docker-init` from an appropriate "libexec" directory · moby/moby@6caaa8c · GitHub
[go: up one dir, main page]

Skip to content

Commit 6caaa8c

Browse files
committed
Prefer loading docker-init from an appropriate "libexec" directory
The `docker-init` binary is not intended to be a user-facing command, and as such it is more appropriate for it to be found in `/usr/libexec` (or similar) than in `PATH` (see the FHS, especially https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04s07.html and https://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#USRLIBLIBRARIESFORPROGRAMMINGANDPA). This adjusts the logic for using that configuration option to take this into account and appropriately search for `docker-init` (or the user's configured alternative) in these directories before falling back to the existing `PATH` lookup behavior. This behavior _used_ to exist for the old `dockerinit` binary (of a similar name and used in a similar way but for an alternative purpose), but that behavior was removed in 4357ed4 when that older `dockerinit` was also removed. Most of this reasoning _also_ applies to `docker-proxy` (and various `containerd-xxx` binaries such as the shims), but this change does not affect those. It would be relatively straightforward to adapt `LookupInitPath` to be a more generic function such as `libexecLookupPath` or similar if we wanted to explore that. See https://github.com/docker/cli/blob/14482589df194a86b2ee07df643ba3277b40df7d/cli-plugins/manager/manager_unix.go for the related path list in the CLI which loads CLI plugins from a similar set of paths (with a similar rationale - plugin binaries are not typically intended to be run directly by users but rather invoked _via_ the CLI binary). Signed-off-by: Tianon Gravi <admwiggin@gmail.com>
1 parent 1855a55 commit 6caaa8c

File tree

3 files changed

+43
-17
lines changed

3 files changed

+43
-17
lines changed

daemon/config/config_linux.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,34 @@ func (conf *Config) GetInitPath() string {
118118
return DefaultInitBinary
119119
}
120120

121+
// LookupInitPath returns an absolute path to the "docker-init" binary by searching relevant "libexec" directories (per FHS 3.0 & 2.3) followed by PATH
122+
func (conf *Config) LookupInitPath() (string, error) {
123+
binary := conf.GetInitPath()
124+
if filepath.IsAbs(binary) {
125+
return binary, nil
126+
}
127+
128+
for _, dir := range []string{
129+
// FHS 3.0: "/usr/libexec includes internal binaries that are not intended to be executed directly by users or shell scripts. Applications may use a single subdirectory under /usr/libexec."
130+
// https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch04s07.html
131+
"/usr/local/libexec/docker",
132+
"/usr/libexec/docker",
133+
134+
// FHS 2.3: "/usr/lib includes object files, libraries, and internal binaries that are not intended to be executed directly by users or shell scripts."
135+
// https://refspecs.linuxfoundation.org/FHS_2.3/fhs-2.3.html#USRLIBLIBRARIESFORPROGRAMMINGANDPA
136+
"/usr/local/lib/docker",
137+
"/usr/lib/docker",
138+
} {
139+
// exec.LookPath has a fast-path short-circuit for paths that contain "/" (skipping the PATH lookup) that then verifies whether the given path is likely to be an actual executable binary (so we invoke that instead of reimplementing the same checks)
140+
if file, err := exec.LookPath(filepath.Join(dir, binary)); err == nil {
141+
return file, nil
142+
}
143+
}
144+
145+
// if we checked all the "libexec" directories and found no matches, fall back to PATH
146+
return exec.LookPath(binary)
147+
}
148+
121149
// GetResolvConf returns the appropriate resolv.conf
122150
// Check setupResolvConf on how this is selected
123151
func (conf *Config) GetResolvConf() string {

daemon/info_unix.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo)
4040
}
4141
v.Runtimes = daemon.configStore.GetAllRuntimes()
4242
v.DefaultRuntime = daemon.configStore.GetDefaultRuntimeName()
43-
v.InitBinary = daemon.configStore.GetInitPath()
4443
v.RuncCommit.ID = "N/A"
4544
v.ContainerdCommit.ID = "N/A"
4645
v.InitCommit.ID = "N/A"
@@ -63,15 +62,17 @@ func (daemon *Daemon) fillPlatformInfo(v *types.Info, sysInfo *sysinfo.SysInfo)
6362
logrus.Warnf("failed to retrieve containerd version: %v", err)
6463
}
6564

66-
defaultInitBinary := daemon.configStore.GetInitPath()
67-
if rv, err := exec.Command(defaultInitBinary, "--version").Output(); err == nil {
65+
v.InitBinary = daemon.configStore.GetInitPath()
66+
if initBinary, err := daemon.configStore.LookupInitPath(); err != nil {
67+
logrus.Warnf("failed to find docker-init: %s", err)
68+
} else if rv, err := exec.Command(initBinary, "--version").Output(); err == nil {
6869
if _, commit, err := parseInitVersion(string(rv)); err != nil {
69-
logrus.Warnf("failed to parse %s version: %s", defaultInitBinary, err)
70+
logrus.Warnf("failed to parse %s version: %s", initBinary, err)
7071
} else {
7172
v.InitCommit.ID = commit
7273
}
7374
} else {
74-
logrus.Warnf("failed to retrieve %s version: %s", defaultInitBinary, err)
75+
logrus.Warnf("failed to retrieve %s version: %s", initBinary, err)
7576
}
7677

7778
// Set expected and actual commits to the same value to prevent the client
@@ -195,21 +196,22 @@ func (daemon *Daemon) fillPlatformVersion(v *types.Version) {
195196
}
196197
}
197198

198-
defaultInitBinary := daemon.configStore.GetInitPath()
199-
if rv, err := exec.Command(defaultInitBinary, "--version").Output(); err == nil {
199+
if initBinary, err := daemon.configStore.LookupInitPath(); err != nil {
200+
logrus.Warnf("failed to find docker-init: %s", err)
201+
} else if rv, err := exec.Command(initBinary, "--version").Output(); err == nil {
200202
if ver, commit, err := parseInitVersion(string(rv)); err != nil {
201-
logrus.Warnf("failed to parse %s version: %s", defaultInitBinary, err)
203+
logrus.Warnf("failed to parse %s version: %s", initBinary, err)
202204
} else {
203205
v.Components = append(v.Components, types.ComponentVersion{
204-
Name: filepath.Base(defaultInitBinary),
206+
Name: filepath.Base(initBinary),
205207
Version: ver,
206208
Details: map[string]string{
207209
"GitCommit": commit,
208210
},
209211
})
210212
}
211213
} else {
212-
logrus.Warnf("failed to retrieve %s version: %s", defaultInitBinary, err)
214+
logrus.Warnf("failed to retrieve %s version: %s", initBinary, err)
213215
}
214216

215217
daemon.fillRootlessVersion(v)

daemon/oci_linux.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"context"
55
"fmt"
66
"os"
7-
"os/exec"
87
"path/filepath"
98
"sort"
109
"strconv"
@@ -748,12 +747,9 @@ func WithCommonOptions(daemon *Daemon, c *container.Container) coci.SpecOpts {
748747
if (c.HostConfig.Init != nil && *c.HostConfig.Init) ||
749748
(c.HostConfig.Init == nil && daemon.configStore.Init) {
750749
s.Process.Args = append([]string{inContainerInitPath, "--", c.Path}, c.Args...)
751-
path := daemon.configStore.InitPath
752-
if path == "" {
753-
path, err = exec.LookPath(dconfig.DefaultInitBinary)
754-
if err != nil {
755-
return err
756-
}
750+
path, err := daemon.configStore.LookupInitPath() // this will fall back to DefaultInitBinary and return an absolute path
751+
if err != nil {
752+
return err
757753
}
758754
s.Mounts = append(s.Mounts, specs.Mount{
759755
Destination: inContainerInitPath,

0 commit comments

Comments
 (0)
0