Skip to content

Commit

Permalink
HvSocket support for containers
Browse files Browse the repository at this point in the history
Applications connecting from the host into the container should use
container-specific VMID. This ID will need to be the same as the
container's VMID inside the guest, which is calculated by HCS/GCS
like it's done in this PR by `HCSIDToGUID`.

To allow the container ID to work with HvSocket on the host, we
need to set up an AddressInfo mapping to tell HvSocket to redirect
the call into the UVM, which is done in this PR by default for
all WCOW containers.

Signed-off-by: Maksim An <maksiman@microsoft.com>
  • Loading branch information
kevpar authored and anmaxvl committed Jan 13, 2025
1 parent 1a8c2e3 commit caf030c
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
6 changes: 6 additions & 0 deletions internal/hcsoci/resources_wcow.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ func allocateWindowsResources(ctx context.Context, coi *createOptionsInternal, r
return err
}
r.Add(driverClosers...)

closer, err := coi.HostingSystem.RedirectContainerHvSocket(coi.actualID)
if err != nil {
return err
}
r.Add(closer)
}

return nil
Expand Down
91 changes: 91 additions & 0 deletions internal/hvsocket/hvsocket.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//go:build windows
// +build windows

package hvsocket

import (
"bytes"
"context"
"encoding/binary"
"fmt"
"strings"
"unicode/utf16"
"unsafe"

"github.com/Microsoft/go-winio/pkg/guid"
"golang.org/x/sys/windows"
)

func HCSIDToGUID(id string) (guid.GUID, error) {
var buf bytes.Buffer
if err := binary.Write(&buf, binary.LittleEndian, utf16.Encode([]rune(strings.ToUpper(id)))); err != nil {
return guid.GUID{}, err
}
g, err := guid.NewV5(guid.GUID{Data1: 0xcab70344, Data2: 0xfacb, Data3: 0x41e4, Data4: [8]byte{0xb5, 0xe5, 0xab, 0x65, 0x92, 0x28, 0x3e, 0x6e}}, buf.Bytes())
if err != nil {
return guid.GUID{}, err
}
return g, nil
}

const (
cAddressFlagPassthru = 0x00000001
cIOCtlHVSocketUpdateAddressInfo = 0x21c004
)

type tAddressInfo struct {
SystemID guid.GUID
VirtualMachineID guid.GUID
SiloID guid.GUID
Flags uint32
}

type Handle windows.Handle

func (h Handle) Release(ctx context.Context) error {
return windows.CloseHandle(windows.Handle(h))
}

func CreateAddressInfo(cid, vmid guid.GUID, passthru bool) (Handle, error) {
path := fmt.Sprintf(`\\.\HvSocketSystem\AddressInfo\{%s}`, cid)
u16, err := windows.UTF16PtrFromString(path)
if err != nil {
return 0, err
}
h, err := windows.CreateFile(
u16,
windows.GENERIC_READ|windows.GENERIC_WRITE,
0,
nil,
windows.CREATE_NEW,
0,
0,
)
if err != nil {
return 0, err
}

addrInfo := tAddressInfo{
SystemID: cid,
VirtualMachineID: vmid,
}
if passthru {
addrInfo.Flags |= cAddressFlagPassthru
}

var ret uint32
if err := windows.DeviceIoControl(
h,
cIOCtlHVSocketUpdateAddressInfo,
(*byte)(unsafe.Pointer(&addrInfo)),
uint32(unsafe.Sizeof(addrInfo)),
nil,
0,
&ret,
nil,
); err != nil {
return 0, err
}

return Handle(h), nil
}
13 changes: 13 additions & 0 deletions internal/uvm/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/Microsoft/hcsshim/internal/cow"
"github.com/Microsoft/hcsshim/internal/hcs"
hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2"
"github.com/Microsoft/hcsshim/internal/hvsocket"
"github.com/Microsoft/hcsshim/internal/log"
"github.com/Microsoft/hcsshim/internal/logfields"
"github.com/Microsoft/hcsshim/internal/oc"
Expand Down Expand Up @@ -232,6 +233,18 @@ func (uvm *UtilityVM) create(ctx context.Context, doc interface{}) error {
return nil
}

func (uvm *UtilityVM) RedirectContainerHvSocket(cid string) (hvsocket.Handle, error) {
containerGUID, err := hvsocket.HCSIDToGUID(cid)
if err != nil {
return 0, err
}
handle, err := hvsocket.CreateAddressInfo(containerGUID, uvm.runtimeID, true)
if err != nil {
return 0, err
}
return handle, nil
}

// Close terminates and releases resources associated with the utility VM.
func (uvm *UtilityVM) Close() error { return uvm.CloseCtx(context.Background()) }

Expand Down

0 comments on commit caf030c

Please sign in to comment.