Просмотр исходного кода

add check for invalid caps

Docker-DCO-1.1-Signed-off-by: Victor Vieux <vieux@docker.com> (github: vieux)
Victor Vieux 11 лет назад
Родитель
Сommit
c04230c42b

+ 4 - 1
daemon/execdriver/lxc/lxc_init_linux.go

@@ -49,7 +49,10 @@ func finalizeNamespace(args *execdriver.InitArgs) error {
 			return fmt.Errorf("clear keep caps %s", err)
 		}
 
-		caps := execdriver.TweakCapabilities(container.Capabilities, strings.Split(args.CapAdd, " "), strings.Split(args.CapDrop, " "))
+		caps, err := execdriver.TweakCapabilities(container.Capabilities, strings.Split(args.CapAdd, " "), strings.Split(args.CapDrop, " "))
+		if err != nil {
+			return err
+		}
 
 		// drop all other capabilities
 		if err := capabilities.DropCapabilities(caps); err != nil {

+ 6 - 3
daemon/execdriver/native/create.go

@@ -43,7 +43,9 @@ func (d *driver) createContainer(c *execdriver.Command) (*libcontainer.Config, e
 			return nil, err
 		}
 	} else {
-		d.setCapabilities(container, c)
+		if err := d.setCapabilities(container, c); err != nil {
+			return nil, err
+		}
 	}
 
 	if err := d.setupCgroups(container, c); err != nil {
@@ -138,8 +140,9 @@ func (d *driver) setPrivileged(container *libcontainer.Config) (err error) {
 	return nil
 }
 
-func (d *driver) setCapabilities(container *libcontainer.Config, c *execdriver.Command) {
-	container.Capabilities = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
+func (d *driver) setCapabilities(container *libcontainer.Config, c *execdriver.Command) (err error) {
+	container.Capabilities, err = execdriver.TweakCapabilities(container.Capabilities, c.CapAdd, c.CapDrop)
+	return err
 }
 
 func (d *driver) setupCgroups(container *libcontainer.Config, c *execdriver.Command) error {

+ 35 - 6
daemon/execdriver/utils.go

@@ -1,34 +1,63 @@
 package execdriver
 
 import (
+	"fmt"
 	"strings"
 
 	"github.com/docker/libcontainer/security/capabilities"
 	"github.com/dotcloud/docker/utils"
 )
 
-func TweakCapabilities(basics, adds, drops []string) []string {
-	var caps []string
+func TweakCapabilities(basics, adds, drops []string) ([]string, error) {
+	var (
+		newCaps []string
+		allCaps = capabilities.GetAllCapabilities()
+	)
 
+	// look for invalid cap in the drop list
+	for _, cap := range drops {
+		if strings.ToLower(cap) == "all" {
+			continue
+		}
+		if !utils.StringsContainsNoCase(allCaps, cap) {
+			return nil, fmt.Errorf("Unknown capability: %s", cap)
+		}
+	}
+
+	// handle --cap-add=all
 	if utils.StringsContainsNoCase(adds, "all") {
 		basics = capabilities.GetAllCapabilities()
 	}
 
 	if !utils.StringsContainsNoCase(drops, "all") {
 		for _, cap := range basics {
+			// skip `all` aready handled above
+			if strings.ToLower(cap) == "all" {
+				continue
+			}
+
+			// if we don't drop `all`, add back all the non-dropped caps
 			if !utils.StringsContainsNoCase(drops, cap) {
-				caps = append(caps, cap)
+				newCaps = append(newCaps, cap)
 			}
 		}
 	}
 
 	for _, cap := range adds {
+		// skip `all` aready handled above
 		if strings.ToLower(cap) == "all" {
 			continue
 		}
-		if !utils.StringsContainsNoCase(caps, cap) {
-			caps = append(caps, cap)
+
+		// look for invalid cap in the drop list
+		if !utils.StringsContainsNoCase(allCaps, cap) {
+			return nil, fmt.Errorf("Unknown capability: %s", cap)
+		}
+
+		// add cap if not already in the list
+		if !utils.StringsContainsNoCase(newCaps, cap) {
+			newCaps = append(newCaps, cap)
 		}
 	}
-	return caps
+	return newCaps, nil
 }

+ 22 - 2
integration-cli/docker_cli_run_test.go

@@ -783,6 +783,16 @@ func TestUnPrivilegedCanMknod(t *testing.T) {
 	logDone("run - test un-privileged can mknod")
 }
 
+func TestCapDropInvalid(t *testing.T) {
+	cmd := exec.Command(dockerBinary, "run", "--cap-drop=CHPASS", "busybox", "ls")
+	out, _, err := runCommandWithOutput(cmd)
+	if err == nil {
+		t.Fatal(err, out)
+	}
+
+	logDone("run - test --cap-drop=CHPASS invalid")
+}
+
 func TestCapDropCannotMknod(t *testing.T) {
 	cmd := exec.Command(dockerBinary, "run", "--cap-drop=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
 	out, _, err := runCommandWithOutput(cmd)
@@ -814,7 +824,7 @@ func TestCapDropALLCannotMknod(t *testing.T) {
 }
 
 func TestCapDropALLAddMknodCannotMknod(t *testing.T) {
-	cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL --cap-add=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
+	cmd := exec.Command(dockerBinary, "run", "--cap-drop=ALL", "--cap-add=MKNOD", "busybox", "sh", "-c", "mknod /tmp/sda b 8 0 && echo ok")
 	out, _, err := runCommandWithOutput(cmd)
 	if err != nil {
 		t.Fatal(err, out)
@@ -828,6 +838,16 @@ func TestCapDropALLAddMknodCannotMknod(t *testing.T) {
 	logDone("run - test --cap-drop=ALL --cap-add=MKNOD can mknod")
 }
 
+func TestCapAddInvalid(t *testing.T) {
+	cmd := exec.Command(dockerBinary, "run", "--cap-add=CHPASS", "busybox", "ls")
+	out, _, err := runCommandWithOutput(cmd)
+	if err == nil {
+		t.Fatal(err, out)
+	}
+
+	logDone("run - test --cap-add=CHPASS invalid")
+}
+
 func TestCapAddCanDownInterface(t *testing.T) {
 	cmd := exec.Command(dockerBinary, "run", "--cap-add=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
 	out, _, err := runCommandWithOutput(cmd)
@@ -859,7 +879,7 @@ func TestCapAddALLCanDownInterface(t *testing.T) {
 }
 
 func TestCapAddALLDropNetAdminCanDownInterface(t *testing.T) {
-	cmd := exec.Command(dockerBinary, "run", "--cap-add=ALL --cap-drop=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
+	cmd := exec.Command(dockerBinary, "run", "--cap-add=ALL", "--cap-drop=NET_ADMIN", "busybox", "sh", "-c", "ip link set eth0 down && echo ok")
 	out, _, err := runCommandWithOutput(cmd)
 	if err == nil {
 		t.Fatal(err, out)