mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
lxc: Work around lxc-start need for private mounts
lxc-start requires / to be mounted private, otherwise the changes it does inside the container (both mounts and unmounts) will propagate out to the host. We work around this by starting up lxc-start in its own namespace where we set / to rprivate. Unfortunately go can't really execute any code between clone and exec, so we can't do this in a nice way. Instead we have a horrible hack that use the unshare command, the shell and the mount command...
This commit is contained in:
parent
d80be57c15
commit
e40f5c7cb9
2 changed files with 31 additions and 1 deletions
17
container.go
17
container.go
|
@ -747,6 +747,7 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
params := []string{
|
params := []string{
|
||||||
|
"lxc-start",
|
||||||
"-n", container.ID,
|
"-n", container.ID,
|
||||||
"-f", container.lxcConfigPath(),
|
"-f", container.lxcConfigPath(),
|
||||||
"--",
|
"--",
|
||||||
|
@ -795,7 +796,21 @@ func (container *Container) Start(hostConfig *HostConfig) error {
|
||||||
params = append(params, "--", container.Path)
|
params = append(params, "--", container.Path)
|
||||||
params = append(params, container.Args...)
|
params = append(params, container.Args...)
|
||||||
|
|
||||||
container.cmd = exec.Command("lxc-start", params...)
|
if RootIsShared() {
|
||||||
|
// lxc-start really needs / to be private, or all kinds of stuff break
|
||||||
|
// What we really want is to clone into a new namespace and then
|
||||||
|
// mount / MS_REC|MS_PRIVATE, but since we can't really clone or fork
|
||||||
|
// without exec in go we have to do this horrible shell hack...
|
||||||
|
shellString :=
|
||||||
|
"mount --make-rprivate /; exec " +
|
||||||
|
utils.ShellQuoteArguments(params)
|
||||||
|
|
||||||
|
params = []string{
|
||||||
|
"unshare", "-m", "--", "/bin/sh", "-c", shellString,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
container.cmd = exec.Command(params[0], params[1:]...)
|
||||||
|
|
||||||
// Setup logging of stdout and stderr to disk
|
// Setup logging of stdout and stderr to disk
|
||||||
if err := container.runtime.LogToDisk(container.stdout, container.logPath("json"), "stdout"); err != nil {
|
if err := container.runtime.LogToDisk(container.stdout, container.logPath("json"), "stdout"); err != nil {
|
||||||
|
|
15
utils.go
15
utils.go
|
@ -2,6 +2,7 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -167,3 +168,17 @@ func parseLxcOpt(opt string) (string, string, error) {
|
||||||
}
|
}
|
||||||
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
|
return strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RootIsShared() bool {
|
||||||
|
if data, err := ioutil.ReadFile("/proc/self/mountinfo"); err == nil {
|
||||||
|
for _, line := range strings.Split(string(data), "\n") {
|
||||||
|
cols := strings.Split(line, " ")
|
||||||
|
if cols[3] == "/" && cols[4] == "/" {
|
||||||
|
return strings.HasPrefix(cols[6], "shared")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No idea, probably safe to assume so
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue