diff --git a/api/server/server.go b/api/server/server.go index bf1a157612..a2723d021b 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -272,14 +272,20 @@ func (s *Server) postContainersKill(version version.Version, w http.ResponseWrit name := vars["name"] // If we have a signal, look at it. Otherwise, do nothing - if sigStr := vars["signal"]; sigStr != "" { + if sigStr := r.Form.Get("signal"); sigStr != "" { // Check if we passed the signal as a number: // The largest legal signal is 31, so let's parse on 5 bits - sig, err := strconv.ParseUint(sigStr, 10, 5) + sigN, err := strconv.ParseUint(sigStr, 10, 5) if err != nil { // The signal is not a number, treat it as a string (either like // "KILL" or like "SIGKILL") - sig = uint64(signal.SignalMap[strings.TrimPrefix(sigStr, "SIG")]) + syscallSig, ok := signal.SignalMap[strings.TrimPrefix(sigStr, "SIG")] + if !ok { + return fmt.Errorf("Invalid signal: %s", sigStr) + } + sig = uint64(syscallSig) + } else { + sig = sigN } if sig == 0 { diff --git a/integration-cli/docker_cli_kill_test.go b/integration-cli/docker_cli_kill_test.go index 1371a0be08..8c0031a4a1 100644 --- a/integration-cli/docker_cli_kill_test.go +++ b/integration-cli/docker_cli_kill_test.go @@ -58,3 +58,62 @@ func (s *DockerSuite) TestKillDifferentUserContainer(c *check.C) { c.Fatal("killed container is still running") } } + +// regression test about correct signal parsing see #13665 +func (s *DockerSuite) TestKillWithSignal(c *check.C) { + runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top") + out, _, err := runCommandWithOutput(runCmd) + c.Assert(err, check.IsNil) + + cid := strings.TrimSpace(out) + c.Assert(waitRun(cid), check.IsNil) + + killCmd := exec.Command(dockerBinary, "kill", "-s", "SIGWINCH", cid) + _, err = runCommand(killCmd) + c.Assert(err, check.IsNil) + + running, err := inspectField(cid, "State.Running") + if running != "true" { + c.Fatal("Container should be in running state after SIGWINCH") + } +} + +func (s *DockerSuite) TestKillWithInvalidSignal(c *check.C) { + runCmd := exec.Command(dockerBinary, "run", "-d", "busybox", "top") + out, _, err := runCommandWithOutput(runCmd) + c.Assert(err, check.IsNil) + + cid := strings.TrimSpace(out) + c.Assert(waitRun(cid), check.IsNil) + + killCmd := exec.Command(dockerBinary, "kill", "-s", "0", cid) + out, _, err = runCommandWithOutput(killCmd) + c.Assert(err, check.NotNil) + if !strings.ContainsAny(out, "Invalid signal: 0") { + c.Fatal("Kill with an invalid signal didn't error out correctly") + } + + running, err := inspectField(cid, "State.Running") + if running != "true" { + c.Fatal("Container should be in running state after an invalid signal") + } + + runCmd = exec.Command(dockerBinary, "run", "-d", "busybox", "top") + out, _, err = runCommandWithOutput(runCmd) + c.Assert(err, check.IsNil) + + cid = strings.TrimSpace(out) + c.Assert(waitRun(cid), check.IsNil) + + killCmd = exec.Command(dockerBinary, "kill", "-s", "SIG42", cid) + out, _, err = runCommandWithOutput(killCmd) + c.Assert(err, check.NotNil) + if !strings.ContainsAny(out, "Invalid signal: SIG42") { + c.Fatal("Kill with an invalid signal error out correctly") + } + + running, err = inspectField(cid, "State.Running") + if running != "true" { + c.Fatal("Container should be in running state after an invalid signal") + } +}