From d12fef1515cb3f0938ea6ed8cab8351e2df2753e Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Thu, 2 Apr 2015 14:12:14 -0700 Subject: [PATCH] Update libcontainaer to d00b8369852285d6a830a8d3b9 Fixes #12015 Signed-off-by: Michael Crosby --- hack/vendor.sh | 2 +- .../docker/libcontainer/apparmor/gen.go | 8 ++-- .../docker/libcontainer/cgroups/fs/freezer.go | 5 ++ .../libcontainer/cgroups/fs/freezer_test.go | 45 +++++++++++++++++ .../cgroups/systemd/apply_systemd.go | 11 +---- .../docker/libcontainer/container_linux.go | 4 +- .../docker/libcontainer/init_linux.go | 3 +- .../docker/libcontainer/nsinit/README.md | 48 +++++++++++-------- .../libcontainer/standard_init_linux.go | 10 ++-- 9 files changed, 96 insertions(+), 40 deletions(-) create mode 100644 vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer_test.go diff --git a/hack/vendor.sh b/hack/vendor.sh index 0246f03cc4..6552cab23b 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -75,7 +75,7 @@ rm -rf src/github.com/docker/distribution mkdir -p src/github.com/docker/distribution mv tmp-digest src/github.com/docker/distribution/digest -clone git github.com/docker/libcontainer c8512754166539461fd860451ff1a0af7491c197 +clone git github.com/docker/libcontainer d00b8369852285d6a830a8d3b966608b2ed89705 # see src/github.com/docker/libcontainer/update-vendor.sh which is the "source of truth" for libcontainer deps (just like this file) rm -rf src/github.com/docker/libcontainer/vendor eval "$(grep '^clone ' src/github.com/docker/libcontainer/update-vendor.sh | grep -v 'github.com/codegangsta/cli' | grep -v 'github.com/Sirupsen/logrus')" diff --git a/vendor/src/github.com/docker/libcontainer/apparmor/gen.go b/vendor/src/github.com/docker/libcontainer/apparmor/gen.go index 825e646d92..4565f6dfec 100644 --- a/vendor/src/github.com/docker/libcontainer/apparmor/gen.go +++ b/vendor/src/github.com/docker/libcontainer/apparmor/gen.go @@ -67,12 +67,12 @@ func generateProfile(out io.Writer) error { data := &data{ Name: "docker-default", } - if tuntablesExists() { + if tunablesExists() { data.Imports = append(data.Imports, "#include ") } else { data.Imports = append(data.Imports, "@{PROC}=/proc/") } - if abstrctionsEsists() { + if abstractionsExists() { data.InnerImports = append(data.InnerImports, "#include ") } if err := compiled.Execute(out, data); err != nil { @@ -82,13 +82,13 @@ func generateProfile(out io.Writer) error { } // check if the tunables/global exist -func tuntablesExists() bool { +func tunablesExists() bool { _, err := os.Stat("/etc/apparmor.d/tunables/global") return err == nil } // check if abstractions/base exist -func abstrctionsEsists() bool { +func abstractionsExists() bool { _, err := os.Stat("/etc/apparmor.d/abstractions/base") return err == nil } diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go index fc8241d1bf..1110e5ff1a 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer.go @@ -1,6 +1,7 @@ package fs import ( + "fmt" "strings" "time" @@ -41,6 +42,10 @@ func (s *FreezerGroup) Set(path string, cgroup *configs.Cgroup) error { } time.Sleep(1 * time.Millisecond) } + case configs.Undefined: + return nil + default: + return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Freezer)) } return nil diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer_test.go b/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer_test.go new file mode 100644 index 0000000000..9ff1886d26 --- /dev/null +++ b/vendor/src/github.com/docker/libcontainer/cgroups/fs/freezer_test.go @@ -0,0 +1,45 @@ +package fs + +import ( + "testing" + + "github.com/docker/libcontainer/configs" +) + +func TestFreezerSetState(t *testing.T) { + helper := NewCgroupTestUtil("freezer", t) + defer helper.cleanup() + + helper.writeFileContents(map[string]string{ + "freezer.state": string(configs.Frozen), + }) + + helper.CgroupData.c.Freezer = configs.Thawed + freezer := &FreezerGroup{} + if err := freezer.Set(helper.CgroupPath, helper.CgroupData.c); err != nil { + t.Fatal(err) + } + + value, err := getCgroupParamString(helper.CgroupPath, "freezer.state") + if err != nil { + t.Fatalf("Failed to parse freezer.state - %s", err) + } + if value != string(configs.Thawed) { + t.Fatal("Got the wrong value, set freezer.state failed.") + } +} + +func TestFreezerSetInvalidState(t *testing.T) { + helper := NewCgroupTestUtil("freezer", t) + defer helper.cleanup() + + const ( + invalidArg configs.FreezerState = "Invalid" + ) + + helper.CgroupData.c.Freezer = invalidArg + freezer := &FreezerGroup{} + if err := freezer.Set(helper.CgroupPath, helper.CgroupData.c); err == nil { + t.Fatal("Failed to return invalid argument error") + } +} diff --git a/vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_systemd.go b/vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_systemd.go index 85ee5db06d..dea196bd06 100644 --- a/vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_systemd.go +++ b/vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_systemd.go @@ -218,16 +218,7 @@ func (m *Manager) Apply(pid int) error { } paths := make(map[string]string) - for _, sysname := range []string{ - "devices", - "memory", - "cpu", - "cpuset", - "cpuacct", - "blkio", - "perf_event", - "freezer", - } { + for sysname := range subsystems { subsystemPath, err := getSubsystemPath(m.Cgroups, sysname) if err != nil { // Don't fail if a cgroup hierarchy was not found, just skip this subsystem diff --git a/vendor/src/github.com/docker/libcontainer/container_linux.go b/vendor/src/github.com/docker/libcontainer/container_linux.go index 54d40617e7..3c077afbd9 100644 --- a/vendor/src/github.com/docker/libcontainer/container_linux.go +++ b/vendor/src/github.com/docker/libcontainer/container_linux.go @@ -140,7 +140,9 @@ func (c *linuxContainer) commandTemplate(p *Process, childPipe *os.File) (*exec. cmd.SysProcAttr = &syscall.SysProcAttr{} } cmd.ExtraFiles = []*os.File{childPipe} - cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL + // NOTE: when running a container with no PID namespace and the parent process spawning the container is + // PID1 the pdeathsig is being delivered to the container's init process by the kernel for some reason + // even with the parent still running. if c.config.ParentDeathSignal > 0 { cmd.SysProcAttr.Pdeathsig = syscall.Signal(c.config.ParentDeathSignal) } diff --git a/vendor/src/github.com/docker/libcontainer/init_linux.go b/vendor/src/github.com/docker/libcontainer/init_linux.go index 0468b2e936..1786b1ed7a 100644 --- a/vendor/src/github.com/docker/libcontainer/init_linux.go +++ b/vendor/src/github.com/docker/libcontainer/init_linux.go @@ -69,7 +69,8 @@ func newContainerInit(t initType, pipe *os.File) (initer, error) { }, nil case initStandard: return &linuxStandardInit{ - config: config, + parentPid: syscall.Getppid(), + config: config, }, nil } return nil, fmt.Errorf("unknown init type %q", t) diff --git a/vendor/src/github.com/docker/libcontainer/nsinit/README.md b/vendor/src/github.com/docker/libcontainer/nsinit/README.md index f321e22719..f2e66a866d 100644 --- a/vendor/src/github.com/docker/libcontainer/nsinit/README.md +++ b/vendor/src/github.com/docker/libcontainer/nsinit/README.md @@ -5,13 +5,15 @@ It is able to spawn new containers or join existing containers. ### How to build? -First to add the `libcontainer/vendor` into your GOPATH. It's because something related with this [issue](https://github.com/docker/libcontainer/issues/210). +First add the `libcontainer/vendor` into your GOPATH. It's because libcontainer +vendors all its dependencies, so it can be built predictably. ``` export GOPATH=$GOPATH:/your/path/to/libcontainer/vendor ``` -Then get into the nsinit folder and get the imported file. Use `make` command to make the nsinit binary. +Then get into the nsinit folder and get the imported file. Use `make` command +to make the nsinit binary. ``` cd libcontainer/nsinit @@ -19,7 +21,8 @@ go get make ``` -We have finished compiling the nsinit package, but a root filesystem must be provided for use along with a container configuration file. +We have finished compiling the nsinit package, but a root filesystem must be +provided for use along with a container configuration file. Choose a proper place to run your container. For example we use `/busybox`. @@ -28,30 +31,37 @@ mkdir /busybox curl -sSL 'https://github.com/jpetazzo/docker-busybox/raw/buildroot-2014.11/rootfs.tar' | tar -xC /busybox ``` -Then you may need to write a configure file named `container.json` in the `/busybox` folder. -Environment, networking, and different capabilities for the container are specified in this file. -The configuration is used for each process executed inside the container -See the `sample_configs` folder for examples of what the container configuration should look like. +Then you may need to write a configuration file named `container.json` in the +`/busybox` folder. Environment, networking, and different capabilities for +the container are specified in this file. The configuration is used for each +process executed inside the container. + +See the `sample_configs` folder for examples of what the container configuration +should look like. ``` cp libcontainer/sample_configs/minimal.json /busybox/container.json cd /busybox ``` -Now the nsinit is ready to work. -To execute `/bin/bash` in the current directory as a container just run the following **as root**: +You can customize `container.json` per your needs. After that, nsinit is +ready to work. + +To execute `/bin/bash` in the current directory as a container just run the +following **as root**: + ```bash -nsinit exec --tty /bin/bash +nsinit exec --tty --config container.json /bin/bash ``` -If you wish to spawn another process inside the container while your -current bash session is running, run the same command again to -get another bash shell (or change the command). If the original -process (PID 1) dies, all other processes spawned inside the container -will be killed and the namespace will be removed. +If you wish to spawn another process inside the container while your current +bash session is running, run the same command again to get another bash shell +(or change the command). If the original process (PID 1) dies, all other +processes spawned inside the container will be killed and the namespace will +be removed. -You can identify if a process is running in a container by -looking to see if `state.json` is in the root of the directory. +You can identify if a process is running in a container by looking to see if +`state.json` is in the root of the directory. -You may also specify an alternate root place where -the `container.json` file is read and where the `state.json` file will be saved. +You may also specify an alternate root directory from where the `container.json` +file is read and where the `state.json` file will be saved. diff --git a/vendor/src/github.com/docker/libcontainer/standard_init_linux.go b/vendor/src/github.com/docker/libcontainer/standard_init_linux.go index 29619d3cdc..282832b568 100644 --- a/vendor/src/github.com/docker/libcontainer/standard_init_linux.go +++ b/vendor/src/github.com/docker/libcontainer/standard_init_linux.go @@ -13,7 +13,8 @@ import ( ) type linuxStandardInit struct { - config *initConfig + parentPid int + config *initConfig } func (l *linuxStandardInit) Init() error { @@ -85,9 +86,10 @@ func (l *linuxStandardInit) Init() error { if err := pdeath.Restore(); err != nil { return err } - // Signal self if parent is already dead. Does nothing if running in a new - // PID namespace, as Getppid will always return 0. - if syscall.Getppid() == 1 { + // compare the parent from the inital start of the init process and make sure that it did not change. + // if the parent changes that means it died and we were reparened to something else so we should + // just kill ourself and not cause problems for someone else. + if syscall.Getppid() != l.parentPid { return syscall.Kill(syscall.Getpid(), syscall.SIGKILL) } return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ())