浏览代码

Update libcontainer to c8512754166539461fd860451ff

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
Michael Crosby 10 年之前
父节点
当前提交
17ecbcf8ff

+ 1 - 1
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 a6044b701c166fe538fc760f9e2dcea3d737cd2a
+clone git github.com/docker/libcontainer c8512754166539461fd860451ff1a0af7491c197
 # 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')"

+ 4 - 4
vendor/src/github.com/docker/libcontainer/cgroups/fs/apply_raw.go

@@ -220,16 +220,16 @@ func getCgroupData(c *configs.Cgroup, pid int) (*data, error) {
 	}, nil
 }
 
-func (raw *data) parent(subsystem string) (string, error) {
+func (raw *data) parent(subsystem, mountpoint string) (string, error) {
 	initPath, err := cgroups.GetInitCgroupDir(subsystem)
 	if err != nil {
 		return "", err
 	}
-	return filepath.Join(raw.root, subsystem, initPath), nil
+	return filepath.Join(mountpoint, initPath), nil
 }
 
 func (raw *data) path(subsystem string) (string, error) {
-	_, err := cgroups.FindCgroupMountpoint(subsystem)
+	mnt, err := cgroups.FindCgroupMountpoint(subsystem)
 	// If we didn't mount the subsystem, there is no point we make the path.
 	if err != nil {
 		return "", err
@@ -240,7 +240,7 @@ func (raw *data) path(subsystem string) (string, error) {
 		return filepath.Join(raw.root, subsystem, raw.cgroup), nil
 	}
 
-	parent, err := raw.parent(subsystem)
+	parent, err := raw.parent(subsystem, mnt)
 	if err != nil {
 		return "", err
 	}

+ 30 - 1
vendor/src/github.com/docker/libcontainer/cgroups/systemd/apply_systemd.go

@@ -43,6 +43,10 @@ var subsystems = map[string]subsystem{
 	"freezer":    &fs.FreezerGroup{},
 }
 
+const (
+	testScopeWait = 4
+)
+
 var (
 	connLock                        sync.Mutex
 	theConn                         *systemd.Conn
@@ -86,16 +90,41 @@ func UseSystemd() bool {
 			}
 		}
 
+		// Ensure the scope name we use doesn't exist. Use the Pid to
+		// avoid collisions between multiple libcontainer users on a
+		// single host.
+		scope := fmt.Sprintf("libcontainer-%d-systemd-test-default-dependencies.scope", os.Getpid())
+		testScopeExists := true
+		for i := 0; i <= testScopeWait; i++ {
+			if _, err := theConn.StopUnit(scope, "replace"); err != nil {
+				if dbusError, ok := err.(dbus.Error); ok {
+					if strings.Contains(dbusError.Name, "org.freedesktop.systemd1.NoSuchUnit") {
+						testScopeExists = false
+						break
+					}
+				}
+			}
+			time.Sleep(time.Millisecond)
+		}
+
+		// Bail out if we can't kill this scope without testing for DefaultDependencies
+		if testScopeExists {
+			return hasStartTransientUnit
+		}
+
 		// Assume StartTransientUnit on a scope allows DefaultDependencies
 		hasTransientDefaultDependencies = true
 		ddf := newProp("DefaultDependencies", false)
-		if _, err := theConn.StartTransientUnit("docker-systemd-test-default-dependencies.scope", "replace", ddf); err != nil {
+		if _, err := theConn.StartTransientUnit(scope, "replace", ddf); err != nil {
 			if dbusError, ok := err.(dbus.Error); ok {
 				if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") {
 					hasTransientDefaultDependencies = false
 				}
 			}
 		}
+
+		// Not critical because of the stop unit logic above.
+		theConn.StopUnit(scope, "replace")
 	}
 	return hasStartTransientUnit
 }

+ 7 - 6
vendor/src/github.com/docker/libcontainer/container_linux.go

@@ -193,12 +193,13 @@ func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe,
 
 func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
 	return &initConfig{
-		Config:  c.config,
-		Args:    process.Args,
-		Env:     process.Env,
-		User:    process.User,
-		Cwd:     process.Cwd,
-		Console: process.consolePath,
+		Config:       c.config,
+		Args:         process.Args,
+		Env:          process.Env,
+		User:         process.User,
+		Cwd:          process.Cwd,
+		Console:      process.consolePath,
+		Capabilities: process.Capabilities,
 	}
 }
 

+ 14 - 8
vendor/src/github.com/docker/libcontainer/init_linux.go

@@ -40,13 +40,14 @@ type network struct {
 
 // initConfig is used for transferring parameters from Exec() to Init()
 type initConfig struct {
-	Args     []string        `json:"args"`
-	Env      []string        `json:"env"`
-	Cwd      string          `json:"cwd"`
-	User     string          `json:"user"`
-	Config   *configs.Config `json:"config"`
-	Console  string          `json:"console"`
-	Networks []*network      `json:"network"`
+	Args         []string        `json:"args"`
+	Env          []string        `json:"env"`
+	Cwd          string          `json:"cwd"`
+	Capabilities []string        `json:"capabilities"`
+	User         string          `json:"user"`
+	Config       *configs.Config `json:"config"`
+	Console      string          `json:"console"`
+	Networks     []*network      `json:"network"`
 }
 
 type initer interface {
@@ -99,7 +100,12 @@ func finalizeNamespace(config *initConfig) error {
 	if err := utils.CloseExecFrom(3); err != nil {
 		return err
 	}
-	w, err := newCapWhitelist(config.Config.Capabilities)
+
+	capabilities := config.Config.Capabilities
+	if config.Capabilities != nil {
+		capabilities = config.Capabilities
+	}
+	w, err := newCapWhitelist(capabilities)
 	if err != nil {
 		return err
 	}

+ 85 - 0
vendor/src/github.com/docker/libcontainer/integration/exec_test.go

@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"io/ioutil"
 	"os"
+	"strconv"
 	"strings"
 	"testing"
 
@@ -395,6 +396,90 @@ func TestProcessEnv(t *testing.T) {
 	}
 }
 
+func TestProcessCaps(t *testing.T) {
+	if testing.Short() {
+		return
+	}
+	root, err := newTestRoot()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(root)
+
+	rootfs, err := newRootfs()
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer remove(rootfs)
+
+	config := newTemplateConfig(rootfs)
+
+	factory, err := libcontainer.New(root, libcontainer.Cgroupfs)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	container, err := factory.Create("test", config)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer container.Destroy()
+
+	processCaps := append(config.Capabilities, "NET_ADMIN")
+
+	var stdout bytes.Buffer
+	pconfig := libcontainer.Process{
+		Args:         []string{"sh", "-c", "cat /proc/self/status"},
+		Env:          standardEnvironment,
+		Capabilities: processCaps,
+		Stdin:        nil,
+		Stdout:       &stdout,
+	}
+	err = container.Start(&pconfig)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	// Wait for process
+	waitProcess(&pconfig, t)
+
+	outputStatus := string(stdout.Bytes())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	lines := strings.Split(outputStatus, "\n")
+
+	effectiveCapsLine := ""
+	for _, l := range lines {
+		line := strings.TrimSpace(l)
+		if strings.Contains(line, "CapEff:") {
+			effectiveCapsLine = line
+			break
+		}
+	}
+
+	if effectiveCapsLine == "" {
+		t.Fatal("Couldn't find effective caps: ", outputStatus)
+	}
+
+	parts := strings.Split(effectiveCapsLine, ":")
+	effectiveCapsStr := strings.TrimSpace(parts[1])
+
+	effectiveCaps, err := strconv.ParseUint(effectiveCapsStr, 16, 64)
+	if err != nil {
+		t.Fatal("Could not parse effective caps", err)
+	}
+
+	var netAdminMask uint64
+	var netAdminBit uint
+	netAdminBit = 12 // from capability.h
+	netAdminMask = 1 << netAdminBit
+	if effectiveCaps&netAdminMask != netAdminMask {
+		t.Fatal("CAP_NET_ADMIN is not set as expected")
+	}
+}
+
 func TestFreeze(t *testing.T) {
 	if testing.Short() {
 		return

+ 57 - 0
vendor/src/github.com/docker/libcontainer/nsinit/README.md

@@ -0,0 +1,57 @@
+## nsinit
+
+`nsinit` is a cli application which demonstrates the use of libcontainer.  
+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).
+
+```
+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.
+
+```
+cd libcontainer/nsinit
+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.
+
+Choose a proper place to run your container. For example we use `/busybox`.
+
+```
+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.
+
+```
+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**:
+```bash
+nsinit exec --tty /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. 
+
+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.

+ 4 - 0
vendor/src/github.com/docker/libcontainer/process.go

@@ -41,6 +41,10 @@ type Process struct {
 	// consolePath is the path to the console allocated to the container.
 	consolePath string
 
+	// Capabilities specify the capabilities to keep when executing the process inside the container
+	// All capbilities not specified will be dropped from the processes capability mask
+	Capabilities []string
+
 	ops processOperations
 }
 

+ 13 - 4
vendor/src/github.com/docker/libcontainer/process_linux.go

@@ -4,6 +4,7 @@ package libcontainer
 
 import (
 	"encoding/json"
+	"errors"
 	"io"
 	"os"
 	"os/exec"
@@ -44,8 +45,12 @@ func (p *setnsProcess) startTime() (string, error) {
 	return system.GetProcessStartTime(p.pid())
 }
 
-func (p *setnsProcess) signal(s os.Signal) error {
-	return p.cmd.Process.Signal(s)
+func (p *setnsProcess) signal(sig os.Signal) error {
+	s, ok := sig.(syscall.Signal)
+	if !ok {
+		return errors.New("os: unsupported signal type")
+	}
+	return syscall.Kill(p.cmd.Process.Pid, s)
 }
 
 func (p *setnsProcess) start() (err error) {
@@ -235,6 +240,10 @@ func (p *initProcess) createNetworkInterfaces() error {
 	return nil
 }
 
-func (p *initProcess) signal(s os.Signal) error {
-	return p.cmd.Process.Signal(s)
+func (p *initProcess) signal(sig os.Signal) error {
+	s, ok := sig.(syscall.Signal)
+	if !ok {
+		return errors.New("os: unsupported signal type")
+	}
+	return syscall.Kill(p.cmd.Process.Pid, s)
 }