Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/jobcontainers/jobcontainer.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,12 +253,12 @@ func (c *JobContainer) CreateProcess(ctx context.Context, config interface{}) (_
Env: env,
Dir: workDir,
Path: absPath,
Args: splitArgs(commandLine),
SysProcAttr: &syscall.SysProcAttr{
// CREATE_BREAKAWAY_FROM_JOB to make sure that we're not inheriting the job object (and by extension its limits)
// from whatever process is going to launch the container.
CreationFlags: windows.CREATE_NEW_PROCESS_GROUP | windows.CREATE_BREAKAWAY_FROM_JOB,
Token: syscall.Token(token),
CmdLine: commandLine,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yay

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ashamed I didn't know of this

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Learning is fun though

},
}
process := newProcess(cmd)
Expand Down
40 changes: 40 additions & 0 deletions test/cri-containerd/jobcontainer_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build functional
// +build functional

package cri_containerd
Expand Down Expand Up @@ -524,3 +525,42 @@ func Test_RunContainer_WorkingDirectory_JobContainer_WCOW(t *testing.T) {
})
}
}

// Test of the fix for the behavior detailed here https://github.com/microsoft/hcsshim/issues/1199
// The underlying issue was that we would escape the args passed to us to form a commandline, and then split the commandline back into args
// to pass to exec.Cmd in the stdlib. exec.Cmd internally does escaping of its own and thus would result in double quoting for certain
// commandlines.
func Test_DoubleQuoting_JobContainer_WCOW(t *testing.T) {
requireFeatures(t, featureWCOWProcess, featureHostProcess)

pullRequiredImages(t, []string{imageJobContainerCmdline})
client := newTestRuntimeClient(t)

podctx := context.Background()
sandboxRequest := getJobContainerPodRequestWCOW(t)

podID := runPodSandbox(t, client, podctx, sandboxRequest)
defer removePodSandbox(t, client, podctx, podID)
defer stopPodSandbox(t, client, podctx, podID)

containerRequest := getJobContainerRequestWCOW(t, podID, sandboxRequest.Config, imageJobContainerCmdline, nil)
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
defer cancel()

containerID := createContainer(t, client, ctx, containerRequest)
defer removeContainer(t, client, ctx, containerID)
startContainer(t, client, ctx, containerID)
defer stopContainer(t, client, ctx, containerID)

execResponse := execSync(t, client, ctx, &runtime.ExecSyncRequest{
ContainerId: containerID,
Cmd: []string{"cmdline.exe", `"quote test"`},
})

expected := `cmdline.exe "quote test"`
// Check that there's no double quoting going on.
// e.g. `cmdline.exe ""quote test"" `
if string(execResponse.Stdout) != expected {
t.Fatalf("expected cmdline for exec to be %q but got %q", expected, string(execResponse.Stdout))
}
}
2 changes: 2 additions & 0 deletions test/cri-containerd/main_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
//go:build functional
// +build functional

package cri_containerd
Expand Down Expand Up @@ -55,6 +56,7 @@ const (
imageJobContainerHNS = "cplatpublic.azurecr.io/jobcontainer_hns:latest"
imageJobContainerETW = "cplatpublic.azurecr.io/jobcontainer_etw:latest"
imageJobContainerVHD = "cplatpublic.azurecr.io/jobcontainer_vhd:latest"
imageJobContainerCmdline = "cplatpublic.azurecr.io/jobcontainer_cmdline:latest"
imageJobContainerWorkDir = "cplatpublic.azurecr.io/jobcontainer_workdir:latest"
alpineAspNet = "mcr.microsoft.com/dotnet/core/aspnet:3.1-alpine3.11"
alpineAspnetUpgrade = "mcr.microsoft.com/dotnet/core/aspnet:3.1.2-alpine3.11"
Expand Down
11 changes: 11 additions & 0 deletions test/cri-containerd/test-images/jobcontainer_cmdline/dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Irrelevant what image version we use for job containers as there's no container <-> host OS version restraint.
FROM golang:1.15.10-nanoserver-1809

# Get administrator privileges
USER containeradministrator

WORKDIR C:\\go\\src\\cmdline
COPY main.go .

RUN go get -d -v ./...
RUN go build -mod=mod
11 changes: 11 additions & 0 deletions test/cri-containerd/test-images/jobcontainer_cmdline/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use this to debug arg parsing issues:

package main

import (
	"fmt"
	"os"
)

func main() {
	for i, arg := range os.Args {
		fmt.Printf("%d: %s\n", i, arg)
	}
}

Find it a little easier to understand with the numbered args.

Copy link
Copy Markdown
Contributor Author

@dcantah dcantah Oct 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you prefer we do this here and check a specific position for the test?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will make it slightly easier to tell what's going on if something breaks


import (
"fmt"
"os"
"strings"
)

func main() {
fmt.Print(strings.Join(os.Args, " "))
}