Browse code

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 <anusha.ragunathan@docker.com>

Anusha Ragunathan authored on 2017/11/29 06:04:13
Showing 2 changed files
... ...
@@ -168,8 +168,19 @@ func (ps *DockerPluginSuite) TestPluginSet(c *check.C) {
168 168
 	defer cancel()
169 169
 
170 170
 	initialValue := "0"
171
+	mntSrc := "foo"
172
+	devPath := "/dev/bar"
173
+
171 174
 	err = plugin.Create(ctx, client, name, func(cfg *plugin.Config) {
172 175
 		cfg.Env = []types.PluginEnv{{Name: "DEBUG", Value: &initialValue, Settable: []string{"value"}}}
176
+		cfg.Mounts = []types.PluginMount{
177
+			{Name: "pmount1", Settable: []string{"source"}, Type: "none", Source: &mntSrc},
178
+			{Name: "pmount2", Settable: []string{"source"}, Type: "none"}, // Mount without source is invalid.
179
+		}
180
+		cfg.Linux.Devices = []types.PluginDevice{
181
+			{Name: "pdev1", Path: &devPath, Settable: []string{"path"}},
182
+			{Name: "pdev2", Settable: []string{"path"}}, // Device without Path is invalid.
183
+		}
173 184
 	})
174 185
 	c.Assert(err, checker.IsNil, check.Commentf("failed to create test plugin"))
175 186
 
... ...
@@ -180,6 +191,23 @@ func (ps *DockerPluginSuite) TestPluginSet(c *check.C) {
180 180
 
181 181
 	env, _ = dockerCmd(c, "plugin", "inspect", "-f", "{{.Settings.Env}}", name)
182 182
 	c.Assert(strings.TrimSpace(env), checker.Equals, "[DEBUG=1]")
183
+
184
+	env, _ = dockerCmd(c, "plugin", "inspect", "-f", "{{with $mount := index .Settings.Mounts 0}}{{$mount.Source}}{{end}}", name)
185
+	c.Assert(strings.TrimSpace(env), checker.Contains, mntSrc)
186
+
187
+	dockerCmd(c, "plugin", "set", name, "pmount1.source=bar")
188
+
189
+	env, _ = dockerCmd(c, "plugin", "inspect", "-f", "{{with $mount := index .Settings.Mounts 0}}{{$mount.Source}}{{end}}", name)
190
+	c.Assert(strings.TrimSpace(env), checker.Contains, "bar")
191
+
192
+	out, _, err := dockerCmdWithError("plugin", "set", name, "pmount2.source=bar2")
193
+	c.Assert(err, checker.NotNil)
194
+	c.Assert(out, checker.Contains, "Plugin config has no mount source")
195
+
196
+	out, _, err = dockerCmdWithError("plugin", "set", name, "pdev2.path=/dev/bar2")
197
+	c.Assert(err, checker.NotNil)
198
+	c.Assert(out, checker.Contains, "Plugin config has no device path")
199
+
183 200
 }
184 201
 
185 202
 func (ps *DockerPluginSuite) TestPluginInstallArgs(c *check.C) {
... ...
@@ -142,6 +142,9 @@ next:
142 142
 				}
143 143
 
144 144
 				// it is, so lets update the settings in memory
145
+				if mount.Source == nil {
146
+					return fmt.Errorf("Plugin config has no mount source")
147
+				}
145 148
 				*mount.Source = s.value
146 149
 				continue next
147 150
 			}
... ...
@@ -159,6 +162,9 @@ next:
159 159
 				}
160 160
 
161 161
 				// it is, so lets update the settings in memory
162
+				if device.Path == nil {
163
+					return fmt.Errorf("Plugin config has no device path")
164
+				}
162 165
 				*device.Path = s.value
163 166
 				continue next
164 167
 			}