From 6572e27df7f3483cfed7a8294c1f6d9cf157809a Mon Sep 17 00:00:00 2001 From: Anusha Ragunathan Date: Tue, 28 Nov 2017 13:04:13 -0800 Subject: [PATCH] Fix potential panic during plugin set. Plugin config can have Mounts without a 'Source' field. In such cases, performing a 'plugin set' on the mount source will panic the daemon. Its the same case for device paths as well. This detects the case and returns error. Signed-off-by: Anusha Ragunathan --- integration-cli/docker_cli_plugins_test.go | 28 ++++++++++++++++++++++ plugin/v2/plugin.go | 6 +++++ 2 files changed, 34 insertions(+) diff --git a/integration-cli/docker_cli_plugins_test.go b/integration-cli/docker_cli_plugins_test.go index 13ae2b0eb6..310067e386 100644 --- a/integration-cli/docker_cli_plugins_test.go +++ b/integration-cli/docker_cli_plugins_test.go @@ -168,8 +168,19 @@ func (ps *DockerPluginSuite) TestPluginSet(c *check.C) { defer cancel() initialValue := "0" + mntSrc := "foo" + devPath := "/dev/bar" + err = plugin.Create(ctx, client, name, func(cfg *plugin.Config) { cfg.Env = []types.PluginEnv{{Name: "DEBUG", Value: &initialValue, Settable: []string{"value"}}} + cfg.Mounts = []types.PluginMount{ + {Name: "pmount1", Settable: []string{"source"}, Type: "none", Source: &mntSrc}, + {Name: "pmount2", Settable: []string{"source"}, Type: "none"}, // Mount without source is invalid. + } + cfg.Linux.Devices = []types.PluginDevice{ + {Name: "pdev1", Path: &devPath, Settable: []string{"path"}}, + {Name: "pdev2", Settable: []string{"path"}}, // Device without Path is invalid. + } }) c.Assert(err, checker.IsNil, check.Commentf("failed to create test plugin")) @@ -180,6 +191,23 @@ func (ps *DockerPluginSuite) TestPluginSet(c *check.C) { env, _ = dockerCmd(c, "plugin", "inspect", "-f", "{{.Settings.Env}}", name) c.Assert(strings.TrimSpace(env), checker.Equals, "[DEBUG=1]") + + env, _ = dockerCmd(c, "plugin", "inspect", "-f", "{{with $mount := index .Settings.Mounts 0}}{{$mount.Source}}{{end}}", name) + c.Assert(strings.TrimSpace(env), checker.Contains, mntSrc) + + dockerCmd(c, "plugin", "set", name, "pmount1.source=bar") + + env, _ = dockerCmd(c, "plugin", "inspect", "-f", "{{with $mount := index .Settings.Mounts 0}}{{$mount.Source}}{{end}}", name) + c.Assert(strings.TrimSpace(env), checker.Contains, "bar") + + out, _, err := dockerCmdWithError("plugin", "set", name, "pmount2.source=bar2") + c.Assert(err, checker.NotNil) + c.Assert(out, checker.Contains, "Plugin config has no mount source") + + out, _, err = dockerCmdWithError("plugin", "set", name, "pdev2.path=/dev/bar2") + c.Assert(err, checker.NotNil) + c.Assert(out, checker.Contains, "Plugin config has no device path") + } func (ps *DockerPluginSuite) TestPluginInstallArgs(c *check.C) { diff --git a/plugin/v2/plugin.go b/plugin/v2/plugin.go index b77536c986..ce3257c0cb 100644 --- a/plugin/v2/plugin.go +++ b/plugin/v2/plugin.go @@ -142,6 +142,9 @@ next: } // it is, so lets update the settings in memory + if mount.Source == nil { + return fmt.Errorf("Plugin config has no mount source") + } *mount.Source = s.value continue next } @@ -159,6 +162,9 @@ next: } // it is, so lets update the settings in memory + if device.Path == nil { + return fmt.Errorf("Plugin config has no device path") + } *device.Path = s.value continue next }