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
39 changes: 5 additions & 34 deletions cmd/shimdiag/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@ import (
"os/signal"
"syscall"

"github.com/Microsoft/go-winio"
"github.com/Microsoft/go-winio/pkg/guid"
"github.com/Microsoft/hcsshim/internal/appargs"
"github.com/Microsoft/hcsshim/internal/cmd"
"github.com/Microsoft/hcsshim/internal/shimdiag"
"github.com/containerd/console"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)

Expand Down Expand Up @@ -46,7 +44,7 @@ var execCommand = cli.Command{
Before: appargs.Validate(appargs.String, appargs.String, appargs.Rest(appargs.String)),
Action: func(clictx *cli.Context) error {
args := clictx.Args()
shim, err := getShim(args[0])
shim, err := shimdiag.GetShim(args[0])
if err != nil {
return err
}
Expand All @@ -69,17 +67,17 @@ var execCommand = cli.Command{
}
}

stdin, err := makePipe(osStdin, true)
stdin, err := cmd.CreatePipeAndListen(osStdin, true)
if err != nil {
return err
}
stdout, err := makePipe(os.Stdout, false)
stdout, err := cmd.CreatePipeAndListen(os.Stdout, false)
if err != nil {
return err
}
var stderr string
if !execTty {
stderr, err = makePipe(os.Stderr, false)
stderr, err = cmd.CreatePipeAndListen(os.Stderr, false)
if err != nil {
return err
}
Expand All @@ -105,30 +103,3 @@ var execCommand = cli.Command{
return cli.NewExitError(errors.New(""), int(resp.ExitCode))
},
}

func makePipe(f interface{}, in bool) (string, error) {
r, err := guid.NewV4()
if err != nil {
return "", err
}
p := `\\.\pipe\` + r.String()
l, err := winio.ListenPipe(p, nil)
if err != nil {
return "", err
}
go func() {
c, err := l.Accept()
if err != nil {
logrus.WithError(err).Error("failed to accept pipe")
return
}

if in {
_, _ = io.Copy(c, f.(io.Reader))
c.Close()
} else {
_, _ = io.Copy(f.(io.Writer), c)
}
}()
return p, nil
}
3 changes: 2 additions & 1 deletion cmd/shimdiag/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"text/tabwriter"

"github.com/Microsoft/hcsshim/internal/appargs"
"github.com/Microsoft/hcsshim/internal/shimdiag"
"github.com/urfave/cli"
)

Expand All @@ -22,7 +23,7 @@ var listCommand = cli.Command{
Before: appargs.Validate(),
Action: func(ctx *cli.Context) error {
pids := ctx.Bool("pids")
shims, err := findShims("")
shims, err := shimdiag.FindShims("")
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/shimdiag/share.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ var shareCommand = cli.Command{
hostPath = args[1]
uvmPath = args[2]
)
shim, err := getShim(shimName)
shim, err := shimdiag.GetShim(shimName)
if err != nil {
return err
}
Expand Down
82 changes: 1 addition & 81 deletions cmd/shimdiag/shimdiag.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,9 @@ import (
"context"
"fmt"
"os"
"path/filepath"
"sort"
"strings"

"github.com/Microsoft/go-winio"
"github.com/Microsoft/hcsshim/internal/shimdiag"
"github.com/containerd/ttrpc"
"github.com/urfave/cli"
"golang.org/x/sys/windows"
)

const (
shimPrefix = `\\.\pipe\ProtectedPrefix\Administrators\containerd-shim-`
shimSuffix = `-pipe`
)

func main() {
Expand All @@ -36,77 +25,8 @@ func main() {
}
}

func findPipes(pattern string) ([]string, error) {
path := `\\.\pipe\*`
path16, err := windows.UTF16FromString(path)
if err != nil {
return nil, err
}
var data windows.Win32finddata
h, err := windows.FindFirstFile(&path16[0], &data)
if err != nil {
return nil, &os.PathError{Op: "FindFirstFile", Path: path, Err: err}
}
var names []string
for {
name := `\\.\pipe\` + windows.UTF16ToString(data.FileName[:])
if matched, _ := filepath.Match(pattern, name); matched {
names = append(names, name)
}
err = windows.FindNextFile(h, &data)
if err == windows.ERROR_NO_MORE_FILES {
break
}
if err != nil {
return nil, &os.PathError{Op: "FindNextFile", Path: path, Err: err}
}
}
return names, nil
}

func findShims(name string) ([]string, error) {
pipes, err := findPipes(shimPrefix + name + "*" + shimSuffix)
if err != nil {
return nil, err
}
for i, p := range pipes {
pipes[i] = p[len(shimPrefix) : len(p)-len(shimSuffix)]
}
sort.Strings(pipes)
return pipes, nil
}

func findShim(name string) (string, error) {
if strings.ContainsAny(name, "*?\\/") {
return "", fmt.Errorf("invalid shim name %s", name)
}
shims, err := findShims(name)
if err != nil {
return "", err
}
if len(shims) == 0 {
return "", fmt.Errorf("no such shim %s", name)
}
if len(shims) > 1 && shims[0] != name {
return "", fmt.Errorf("multiple shims beginning with %s", name)
}
return shims[0], nil
}

func getShim(name string) (*ttrpc.Client, error) {
shim, err := findShim(name)
if err != nil {
return nil, err
}
conn, err := winio.DialPipe(shimPrefix+shim+shimSuffix, nil)
if err != nil {
return nil, err
}
return ttrpc.NewClient(conn), nil
}

func getPid(shimName string) (int32, error) {
shim, err := getShim(shimName)
shim, err := shimdiag.GetShim(shimName)
if err != nil {
return 0, err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/shimdiag/stacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ var stacksCommand = cli.Command{
ArgsUsage: "<shim name>",
Before: appargs.Validate(appargs.String),
Action: func(c *cli.Context) error {
shim, err := getShim(c.Args()[0])
shim, err := shimdiag.GetShim(c.Args()[0])
if err != nil {
return err
}
Expand Down
44 changes: 44 additions & 0 deletions internal/cmd/io_npipe.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package cmd
import (
"context"
"io"
"net"
"sync"

winio "github.com/Microsoft/go-winio"
"github.com/Microsoft/go-winio/pkg/guid"
"github.com/Microsoft/hcsshim/internal/log"
"github.com/sirupsen/logrus"
)
Expand Down Expand Up @@ -136,3 +138,45 @@ func (nio *npipeio) StderrPath() string {
func (nio *npipeio) Terminal() bool {
return nio.terminal
}

// CreatePipeAndListen is a helper function to create a pipe listener
// and accept connections. Returns the created pipe path on success.
Comment thread
katiewasnothere marked this conversation as resolved.
//
// If `in` is true, `f` should implement io.Reader
// If `in` is false, `f` should implement io.Writer
func CreatePipeAndListen(f interface{}, in bool) (string, error) {
p, l, err := CreateNamedPipeListener()
if err != nil {
return "", err
}
go func() {
c, err := l.Accept()
if err != nil {
logrus.WithError(err).Error("failed to accept pipe")
return
}

if in {
_, _ = io.Copy(c, f.(io.Reader))
c.Close()
} else {
_, _ = io.Copy(f.(io.Writer), c)
}
}()
return p, nil
}

// CreateNamedPipeListener is a helper function to create and return a pipe listener
// and it's created path.
func CreateNamedPipeListener() (string, net.Listener, error) {
g, err := guid.NewV4()
if err != nil {
return "", nil, err
}
p := `\\.\pipe\` + g.String()
l, err := winio.ListenPipe(p, nil)
if err != nil {
return "", nil, err
}
return p, l, nil
}
19 changes: 1 addition & 18 deletions internal/devices/assigned_devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"net"
"strings"

winio "github.com/Microsoft/go-winio"
"github.com/Microsoft/go-winio/pkg/guid"
"github.com/Microsoft/hcsshim/internal/cmd"
"github.com/Microsoft/hcsshim/internal/log"
"github.com/Microsoft/hcsshim/internal/shimdiag"
Expand Down Expand Up @@ -62,7 +60,7 @@ func AddDevice(ctx context.Context, vm *uvm.UtilityVM, idType, deviceID, deviceU
// parent bus device for the children devices' location paths from the uvm's view.
// Returns a slice of strings representing the resulting children location paths
func getChildrenDeviceLocationPaths(ctx context.Context, vm *uvm.UtilityVM, vmBusInstanceID string, deviceUtilPath string) ([]string, error) {
p, l, err := createNamedPipeListener()
p, l, err := cmd.CreateNamedPipeListener()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -111,21 +109,6 @@ func createDeviceUtilChildrenCommand(deviceUtilPath string, vmBusInstanceID stri
return args
}

// createNamedPipeListener is a helper function to create and return a pipe listener
// and it's created path.
func createNamedPipeListener() (string, net.Listener, error) {
g, err := guid.NewV4()
if err != nil {
return "", nil, err
}
p := `\\.\pipe\` + g.String()
l, err := winio.ListenPipe(p, nil)
if err != nil {
return "", nil, err
}
return p, l, nil
}

// readCsPipeOutput is a helper function that connects to a listener and reads
// the connection's comma separated output until done. resulting comma separated
// values are returned in the `result` param. The `errChan` param is used to
Expand Down
87 changes: 87 additions & 0 deletions internal/shimdiag/shimdiag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package shimdiag

import (
fmt "fmt"
"os"
"path/filepath"
"sort"
strings "strings"

"github.com/Microsoft/go-winio"
"github.com/containerd/ttrpc"
"golang.org/x/sys/windows"
)

const (
shimPrefix = `\\.\pipe\ProtectedPrefix\Administrators\containerd-shim-`
shimSuffix = `-pipe`
)

func findPipes(pattern string) ([]string, error) {
path := `\\.\pipe\*`
path16, err := windows.UTF16FromString(path)
if err != nil {
return nil, err
}
var data windows.Win32finddata
h, err := windows.FindFirstFile(&path16[0], &data)
if err != nil {
return nil, &os.PathError{Op: "FindFirstFile", Path: path, Err: err}
}
var names []string
for {
name := `\\.\pipe\` + windows.UTF16ToString(data.FileName[:])
if matched, _ := filepath.Match(pattern, name); matched {
names = append(names, name)
}
err = windows.FindNextFile(h, &data)
if err == windows.ERROR_NO_MORE_FILES {
break
}
if err != nil {
return nil, &os.PathError{Op: "FindNextFile", Path: path, Err: err}
}
}
return names, nil
}

func FindShims(name string) ([]string, error) {
pipes, err := findPipes(shimPrefix + name + "*" + shimSuffix)
if err != nil {
return nil, err
}
for i, p := range pipes {
pipes[i] = p[len(shimPrefix) : len(p)-len(shimSuffix)]
}
sort.Strings(pipes)
return pipes, nil
}

func findShim(name string) (string, error) {
if strings.ContainsAny(name, "*?\\/") {
return "", fmt.Errorf("invalid shim name %s", name)
}
shims, err := FindShims(name)
if err != nil {
return "", err
}
if len(shims) == 0 {
return "", fmt.Errorf("no such shim %s", name)
}
if len(shims) > 1 && shims[0] != name {
return "", fmt.Errorf("multiple shims beginning with %s", name)
}
return shims[0], nil
}

func GetShim(name string) (*ttrpc.Client, error) {
shim, err := findShim(name)
if err != nil {
return nil, err
}
conn, err := winio.DialPipe(shimPrefix+shim+shimSuffix, nil)
if err != nil {
return nil, err
}
return ttrpc.NewClient(conn), nil
}
Loading