Merge pull request #20601 from giuseppe/use-rootless-from-storage

rootless: use functionalities from c/storage
This commit is contained in:
openshift-merge-bot[bot]
2023-11-13 16:30:58 +00:00
committed by GitHub
20 changed files with 227 additions and 134 deletions

6
go.mod
View File

@ -19,7 +19,7 @@ require (
github.com/containers/libhvee v0.4.1-0.20231106202301-9651e31ae734 github.com/containers/libhvee v0.4.1-0.20231106202301-9651e31ae734
github.com/containers/ocicrypt v1.1.9 github.com/containers/ocicrypt v1.1.9
github.com/containers/psgo v1.8.0 github.com/containers/psgo v1.8.0
github.com/containers/storage v1.50.3-0.20231101112703-6e72f11598fb github.com/containers/storage v1.50.3-0.20231108224651-a56f2b2fecfd
github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09
github.com/coreos/stream-metadata-go v0.4.3 github.com/coreos/stream-metadata-go v0.4.3
github.com/crc-org/vfkit v0.1.2-0.20231030102423-f3c783d34420 github.com/crc-org/vfkit v0.1.2-0.20231030102423-f3c783d34420
@ -83,7 +83,7 @@ require (
require ( require (
dario.cat/mergo v1.0.0 // indirect dario.cat/mergo v1.0.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Microsoft/hcsshim v0.12.0-rc.0 // indirect github.com/Microsoft/hcsshim v0.12.0-rc.1 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect github.com/VividCortex/ewma v1.2.0 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/aead/serpent v0.0.0-20160714141033-fba169763ea6 // indirect github.com/aead/serpent v0.0.0-20160714141033-fba169763ea6 // indirect
@ -160,7 +160,7 @@ require (
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/patternmatcher v0.5.0 // indirect github.com/moby/patternmatcher v0.5.0 // indirect
github.com/moby/sys/mountinfo v0.6.2 // indirect github.com/moby/sys/mountinfo v0.7.1 // indirect
github.com/moby/sys/sequential v0.5.0 // indirect github.com/moby/sys/sequential v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect

11
go.sum
View File

@ -67,8 +67,8 @@ github.com/Microsoft/hcsshim v0.8.15/go.mod h1:x38A4YbHbdxJtc0sF6oIz+RG0npwSCAvn
github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600= github.com/Microsoft/hcsshim v0.8.16/go.mod h1:o5/SZqmR7x9JNKsW3pu+nqHm0MF8vbA+VxGOoXdC600=
github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4= github.com/Microsoft/hcsshim v0.8.21/go.mod h1:+w2gRZ5ReXQhFOrvSQeNfhrYB/dg3oDwTOcER2fw4I4=
github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc=
github.com/Microsoft/hcsshim v0.12.0-rc.0 h1:wX/F5huJxH9APBkhKSEAqaiZsuBvbbDnyBROZAqsSaY= github.com/Microsoft/hcsshim v0.12.0-rc.1 h1:Hy+xzYujv7urO5wrgcG58SPMOXNLrj4WCJbySs2XX/A=
github.com/Microsoft/hcsshim v0.12.0-rc.0/go.mod h1:rvOnw3YlfoNnEp45wReUngvsXbwRW+AFQ10GVjG1kMU= github.com/Microsoft/hcsshim v0.12.0-rc.1/go.mod h1:Y1a1S0QlYp1mBpyvGiuEdOfZqnao+0uX5AWHXQ5NhZU=
github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU= github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5hlzMzRKMLyo42nCZ9oml8AdTlq/0cvIaBv6tK1RehU=
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
@ -276,8 +276,8 @@ github.com/containers/ocicrypt v1.1.9/go.mod h1:dTKx1918d8TDkxXvarscpNVY+lyPakPN
github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY= github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY=
github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc= github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc=
github.com/containers/storage v1.43.0/go.mod h1:uZ147thiIFGdVTjMmIw19knttQnUCl3y9zjreHrg11s= github.com/containers/storage v1.43.0/go.mod h1:uZ147thiIFGdVTjMmIw19knttQnUCl3y9zjreHrg11s=
github.com/containers/storage v1.50.3-0.20231101112703-6e72f11598fb h1:g1IJUHmHZuHa1YPvIiYjWrhysb+qEiiImA8p8mENhiE= github.com/containers/storage v1.50.3-0.20231108224651-a56f2b2fecfd h1:IidA+YID5VdlNNJ0xcRdOcaPWs+fP0IFJqFRVuwtPjo=
github.com/containers/storage v1.50.3-0.20231101112703-6e72f11598fb/go.mod h1:LpKczONfqahkVHFdZGPUg/xYZVjd/qqisRu0TkO4u8k= github.com/containers/storage v1.50.3-0.20231108224651-a56f2b2fecfd/go.mod h1:ybl8a3j1PPtpyaEi/5A6TOFs+5TrEyObeKJzVtkUlfc=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
@ -784,8 +784,9 @@ github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M
github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/patternmatcher v0.5.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A=
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=

View File

@ -45,6 +45,23 @@ const (
numSig = 65 // max number of signals numSig = 65 // max number of signals
) )
func init() {
rootlessUIDInit := int(C.rootless_uid())
rootlessGIDInit := int(C.rootless_gid())
if rootlessUIDInit != 0 {
// we need this if we joined the user+mount namespace from the C code.
if err := os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done"); err != nil {
logrus.Errorf("Failed to set environment variable %s as %s", "_CONTAINERS_USERNS_CONFIGURED", "done")
}
if err := os.Setenv("_CONTAINERS_ROOTLESS_UID", strconv.Itoa(rootlessUIDInit)); err != nil {
logrus.Errorf("Failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_UID", rootlessUIDInit)
}
if err := os.Setenv("_CONTAINERS_ROOTLESS_GID", strconv.Itoa(rootlessGIDInit)); err != nil {
logrus.Errorf("Failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_GID", rootlessGIDInit)
}
}
}
func runInUser() error { func runInUser() error {
return os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done") return os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done")
} }
@ -56,60 +73,21 @@ var (
// IsRootless tells us if we are running in rootless mode // IsRootless tells us if we are running in rootless mode
func IsRootless() bool { func IsRootless() bool {
isRootlessOnce.Do(func() { // unshare.IsRootless() is used to check if a user namespace is required.
rootlessUIDInit := int(C.rootless_uid()) // Here we need to make sure that nested podman instances act
rootlessGIDInit := int(C.rootless_gid()) // as if they have root privileges and pick paths on the host
if rootlessUIDInit != 0 { // that would normally be used for root.
// This happens if we joined the user+mount namespace as part of return unshare.IsRootless() && unshare.GetRootlessUID() > 0
if err := os.Setenv("_CONTAINERS_USERNS_CONFIGURED", "done"); err != nil {
logrus.Errorf("Failed to set environment variable %s as %s", "_CONTAINERS_USERNS_CONFIGURED", "done")
}
if err := os.Setenv("_CONTAINERS_ROOTLESS_UID", strconv.Itoa(rootlessUIDInit)); err != nil {
logrus.Errorf("Failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_UID", rootlessUIDInit)
}
if err := os.Setenv("_CONTAINERS_ROOTLESS_GID", strconv.Itoa(rootlessGIDInit)); err != nil {
logrus.Errorf("Failed to set environment variable %s as %d", "_CONTAINERS_ROOTLESS_GID", rootlessGIDInit)
}
}
isRootless = os.Geteuid() != 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != ""
if !isRootless {
hasCapSysAdmin, err := unshare.HasCapSysAdmin()
if err != nil {
logrus.Warnf("Failed to read CAP_SYS_ADMIN presence for the current process")
}
if err == nil && !hasCapSysAdmin {
isRootless = true
}
}
})
return isRootless
} }
// GetRootlessUID returns the UID of the user in the parent userNS // GetRootlessUID returns the UID of the user in the parent userNS
func GetRootlessUID() int { func GetRootlessUID() int {
uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID") return unshare.GetRootlessUID()
if uidEnv != "" {
u, _ := strconv.Atoi(uidEnv)
return u
}
return os.Geteuid()
} }
// GetRootlessGID returns the GID of the user in the parent userNS // GetRootlessGID returns the GID of the user in the parent userNS
func GetRootlessGID() int { func GetRootlessGID() int {
gidEnv := os.Getenv("_CONTAINERS_ROOTLESS_GID") return unshare.GetRootlessGID()
if gidEnv != "" {
u, _ := strconv.Atoi(gidEnv)
return u
}
/* If the _CONTAINERS_ROOTLESS_UID is set, assume the gid==uid. */
uidEnv := os.Getenv("_CONTAINERS_ROOTLESS_UID")
if uidEnv != "" {
u, _ := strconv.Atoi(uidEnv)
return u
}
return os.Getegid()
} }
func tryMappingTool(uid bool, pid int, hostID int, mappings []idtools.IDMap) error { func tryMappingTool(uid bool, pid int, hostID int, mappings []idtools.IDMap) error {

View File

@ -12,14 +12,16 @@ import (
"syscall" "syscall"
"time" "time"
"go.opencensus.io/trace"
"github.com/Microsoft/hcsshim/internal/cow" "github.com/Microsoft/hcsshim/internal/cow"
hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2"
"github.com/Microsoft/hcsshim/internal/log" "github.com/Microsoft/hcsshim/internal/log"
"github.com/Microsoft/hcsshim/internal/oc" "github.com/Microsoft/hcsshim/internal/oc"
"github.com/Microsoft/hcsshim/internal/protocol/guestrequest"
"github.com/Microsoft/hcsshim/internal/vmcompute" "github.com/Microsoft/hcsshim/internal/vmcompute"
"go.opencensus.io/trace"
) )
// ContainerError is an error encountered in HCS
type Process struct { type Process struct {
handleLock sync.RWMutex handleLock sync.RWMutex
handle vmcompute.HcsProcess handle vmcompute.HcsProcess
@ -50,35 +52,6 @@ func newProcess(process vmcompute.HcsProcess, processID int, computeSystem *Syst
} }
} }
type processModifyRequest struct {
Operation string
ConsoleSize *consoleSize `json:",omitempty"`
CloseHandle *closeHandle `json:",omitempty"`
}
type consoleSize struct {
Height uint16
Width uint16
}
type closeHandle struct {
Handle string
}
type processStatus struct {
ProcessID uint32
Exited bool
ExitCode uint32
LastWaitResult int32
}
const stdIn string = "StdIn"
const (
modifyConsoleSize string = "ConsoleSize"
modifyCloseHandle string = "CloseHandle"
)
// Pid returns the process ID of the process within the container. // Pid returns the process ID of the process within the container.
func (process *Process) Pid() int { func (process *Process) Pid() int {
return process.processID return process.processID
@ -260,14 +233,14 @@ func (process *Process) waitBackground() {
process.handleLock.RLock() process.handleLock.RLock()
defer process.handleLock.RUnlock() defer process.handleLock.RUnlock()
// Make sure we didnt race with Close() here // Make sure we didn't race with Close() here
if process.handle != 0 { if process.handle != 0 {
propertiesJSON, resultJSON, err = vmcompute.HcsGetProcessProperties(ctx, process.handle) propertiesJSON, resultJSON, err = vmcompute.HcsGetProcessProperties(ctx, process.handle)
events := processHcsResult(ctx, resultJSON) events := processHcsResult(ctx, resultJSON)
if err != nil { if err != nil {
err = makeProcessError(process, operation, err, events) err = makeProcessError(process, operation, err, events)
} else { } else {
properties := &processStatus{} properties := &hcsschema.ProcessStatus{}
err = json.Unmarshal([]byte(propertiesJSON), properties) err = json.Unmarshal([]byte(propertiesJSON), properties)
if err != nil { if err != nil {
err = makeProcessError(process, operation, err, nil) err = makeProcessError(process, operation, err, nil)
@ -318,10 +291,9 @@ func (process *Process) ResizeConsole(ctx context.Context, width, height uint16)
if process.handle == 0 { if process.handle == 0 {
return makeProcessError(process, operation, ErrAlreadyClosed, nil) return makeProcessError(process, operation, ErrAlreadyClosed, nil)
} }
modifyRequest := hcsschema.ProcessModifyRequest{
modifyRequest := processModifyRequest{ Operation: guestrequest.ModifyProcessConsoleSize,
Operation: modifyConsoleSize, ConsoleSize: &hcsschema.ConsoleSize{
ConsoleSize: &consoleSize{
Height: height, Height: height,
Width: width, Width: width,
}, },
@ -421,18 +393,12 @@ func (process *Process) CloseStdin(ctx context.Context) (err error) {
return makeProcessError(process, operation, ErrAlreadyClosed, nil) return makeProcessError(process, operation, ErrAlreadyClosed, nil)
} }
process.stdioLock.Lock()
defer process.stdioLock.Unlock()
if process.stdin == nil {
return nil
}
//HcsModifyProcess request to close stdin will fail if the process has already exited //HcsModifyProcess request to close stdin will fail if the process has already exited
if !process.stopped() { if !process.stopped() {
modifyRequest := processModifyRequest{ modifyRequest := hcsschema.ProcessModifyRequest{
Operation: modifyCloseHandle, Operation: guestrequest.CloseProcessHandle,
CloseHandle: &closeHandle{ CloseHandle: &hcsschema.CloseHandle{
Handle: stdIn, Handle: guestrequest.STDInHandle,
}, },
} }
@ -448,8 +414,12 @@ func (process *Process) CloseStdin(ctx context.Context) (err error) {
} }
} }
process.stdin.Close() process.stdioLock.Lock()
process.stdin = nil defer process.stdioLock.Unlock()
if process.stdin != nil {
process.stdin.Close()
process.stdin = nil
}
return nil return nil
} }

View File

@ -9,6 +9,8 @@
package hcsschema package hcsschema
import "github.com/Microsoft/hcsshim/internal/protocol/guestrequest"
type CloseHandle struct { type CloseHandle struct {
Handle string `json:"Handle,omitempty"` Handle guestrequest.STDIOHandle `json:"Handle,omitempty"` // NOTE: Swagger generated as string. Locally updated.
} }

View File

@ -9,8 +9,11 @@
package hcsschema package hcsschema
type ConsoleSize struct { // NOTE: Swagger generated fields as int32. Locally updated to uint16 to match documentation.
Height int32 `json:"Height,omitempty"` // https://learn.microsoft.com/en-us/virtualization/api/hcs/schemareference#ConsoleSize
Width int32 `json:"Width,omitempty"` type ConsoleSize struct {
Height uint16 `json:"Height,omitempty"`
Width uint16 `json:"Width,omitempty"`
} }

View File

@ -9,9 +9,11 @@
package hcsschema package hcsschema
// Passed to HcsRpc_ModifyProcess import "github.com/Microsoft/hcsshim/internal/protocol/guestrequest"
// Passed to HcsRpc_ModifyProcess
type ProcessModifyRequest struct { type ProcessModifyRequest struct {
Operation string `json:"Operation,omitempty"` Operation guestrequest.ProcessModifyOperation `json:"Operation,omitempty"` // NOTE: Swagger generated as string. Locally updated.
ConsoleSize *ConsoleSize `json:"ConsoleSize,omitempty"` ConsoleSize *ConsoleSize `json:"ConsoleSize,omitempty"`

View File

@ -9,13 +9,16 @@
package hcsschema package hcsschema
// Status of a process running in a container // NOTE: Swagger generated fields as int32. Locally updated to uint16 to match documentation.
// https://learn.microsoft.com/en-us/virtualization/api/hcs/schemareference#ConsoleSize
// Status of a process running in a container
type ProcessStatus struct { type ProcessStatus struct {
ProcessId int32 `json:"ProcessId,omitempty"` ProcessId uint32 `json:"ProcessId,omitempty"` // NOTE: Swagger generated as int32. Locally updated to match documentation.
Exited bool `json:"Exited,omitempty"` Exited bool `json:"Exited,omitempty"`
ExitCode int32 `json:"ExitCode,omitempty"` ExitCode uint32 `json:"ExitCode,omitempty"` // NOTE: Swagger generated as int32. Locally updated to match documentation.
LastWaitResult int32 `json:"LastWaitResult,omitempty"` LastWaitResult int32 `json:"LastWaitResult,omitempty"`
} }

View File

@ -304,11 +304,22 @@ func (computeSystem *System) WaitError() error {
return computeSystem.waitError return computeSystem.waitError
} }
// Wait synchronously waits for the compute system to shutdown or terminate. If // Wait synchronously waits for the compute system to shutdown or terminate.
// the compute system has already exited returns the previous error (if any). // If the compute system has already exited returns the previous error (if any).
func (computeSystem *System) Wait() error { func (computeSystem *System) Wait() error {
<-computeSystem.WaitChannel() return computeSystem.WaitCtx(context.Background())
return computeSystem.WaitError() }
// WaitCtx synchronously waits for the compute system to shutdown or terminate, or the context to be cancelled.
//
// See [System.Wait] for more information.
func (computeSystem *System) WaitCtx(ctx context.Context) error {
select {
case <-computeSystem.WaitChannel():
return computeSystem.WaitError()
case <-ctx.Done():
return ctx.Err()
}
} }
// stopped returns true if the compute system stopped. // stopped returns true if the compute system stopped.
@ -735,9 +746,17 @@ func (computeSystem *System) OpenProcess(ctx context.Context, pid int) (*Process
} }
// Close cleans up any state associated with the compute system but does not terminate or wait for it. // Close cleans up any state associated with the compute system but does not terminate or wait for it.
func (computeSystem *System) Close() (err error) { func (computeSystem *System) Close() error {
return computeSystem.CloseCtx(context.Background())
}
// CloseCtx is similar to [System.Close], but accepts a context.
//
// The context is used for all operations, including waits, so timeouts/cancellations may prevent
// proper system cleanup.
func (computeSystem *System) CloseCtx(ctx context.Context) (err error) {
operation := "hcs::System::Close" operation := "hcs::System::Close"
ctx, span := oc.StartSpan(context.Background(), operation) ctx, span := oc.StartSpan(ctx, operation)
defer span.End() defer span.End()
defer func() { oc.SetSpanStatus(span, err) }() defer func() { oc.SetSpanStatus(span, err) }()
span.AddAttributes(trace.StringAttribute("cid", computeSystem.id)) span.AddAttributes(trace.StringAttribute("cid", computeSystem.id))

View File

@ -9,13 +9,16 @@ import (
"reflect" "reflect"
"time" "time"
"github.com/containerd/containerd/log"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
) )
const TimeFormat = log.RFC3339NanoFixed // TimeFormat is [time.RFC3339Nano] with nanoseconds padded using
// zeros to ensure the formatted time is always the same number of
// characters.
// Based on RFC3339NanoFixed from github.com/containerd/log
const TimeFormat = "2006-01-02T15:04:05.000000000Z07:00"
func FormatTime(t time.Time) string { func FormatTime(t time.Time) string {
return t.Format(TimeFormat) return t.Format(TimeFormat)

View File

@ -6,7 +6,6 @@ import (
"time" "time"
"github.com/Microsoft/hcsshim/internal/logfields" "github.com/Microsoft/hcsshim/internal/logfields"
"github.com/containerd/containerd/log"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"go.opencensus.io/trace" "go.opencensus.io/trace"
) )
@ -30,7 +29,7 @@ type Hook struct {
// An empty string disables formatting. // An empty string disables formatting.
// When disabled, the fall back will the JSON encoding, if enabled. // When disabled, the fall back will the JSON encoding, if enabled.
// //
// Default is [github.com/containerd/containerd/log.RFC3339NanoFixed]. // Default is [TimeFormat].
TimeFormat string TimeFormat string
// Duration format converts a [time.Duration] fields to an appropriate encoding. // Duration format converts a [time.Duration] fields to an appropriate encoding.
@ -49,7 +48,7 @@ var _ logrus.Hook = &Hook{}
func NewHook() *Hook { func NewHook() *Hook {
return &Hook{ return &Hook{
TimeFormat: log.RFC3339NanoFixed, TimeFormat: TimeFormat,
DurationFormat: DurationFormatString, DurationFormat: DurationFormatString,
AddSpanContext: true, AddSpanContext: true,
} }

View File

@ -0,0 +1,12 @@
package log
import (
"github.com/sirupsen/logrus"
)
type NopFormatter struct{}
var _ logrus.Formatter = NopFormatter{}
// Format does nothing and returns a nil slice.
func (NopFormatter) Format(*logrus.Entry) ([]byte, error) { return nil, nil }

View File

@ -5,7 +5,7 @@ package guestrequest
type RequestType string type RequestType string
type ResourceType string type ResourceType string
// RequestType const // RequestType const.
const ( const (
RequestTypeAdd RequestType = "Add" RequestTypeAdd RequestType = "Add"
RequestTypeRemove RequestType = "Remove" RequestTypeRemove RequestType = "Remove"
@ -54,3 +54,23 @@ var (
"305891a9-b251-5dfe-91a2-c25d9212275b", "305891a9-b251-5dfe-91a2-c25d9212275b",
} }
) )
// constants for v2 schema ProcessModifyRequest
// Operation type for [hcsschema.ProcessModifyRequest].
type ProcessModifyOperation string
const (
ModifyProcessConsoleSize ProcessModifyOperation = "ConsoleSize"
CloseProcessHandle ProcessModifyOperation = "CloseHandle"
)
// Standard IO handle(s) to close for [hcsschema.CloseHandle] in [hcsschema.ProcessModifyRequest].
type STDIOHandle string
const (
STDInHandle STDIOHandle = "StdIn"
STDOutHandle STDIOHandle = "StdOut"
STDErrHandle STDIOHandle = "StdErr"
AllHandles STDIOHandle = "All"
)

View File

@ -7,6 +7,10 @@ package wclayer
import ( import (
"context" "context"
"fmt"
"os"
"path/filepath"
"strconv"
"syscall" "syscall"
"github.com/Microsoft/go-winio/pkg/guid" "github.com/Microsoft/go-winio/pkg/guid"
@ -101,3 +105,23 @@ func layerPathsToDescriptors(ctx context.Context, parentLayerPaths []string) ([]
return layers, nil return layers, nil
} }
// GetLayerUvmBuild looks for a file named `uvmbuildversion` at `layerPath\uvmbuildversion` and returns the
// build number of the UVM from that file.
func GetLayerUvmBuild(layerPath string) (uint16, error) {
data, err := os.ReadFile(filepath.Join(layerPath, UvmBuildFileName))
if err != nil {
return 0, err
}
ver, err := strconv.ParseUint(string(data), 10, 16)
if err != nil {
return 0, err
}
return uint16(ver), nil
}
// WriteLayerUvmBuildFile writes a file at path `layerPath\uvmbuildversion` that contains the given `build`
// version for future reference.
func WriteLayerUvmBuildFile(layerPath string, build uint16) error {
return os.WriteFile(filepath.Join(layerPath, UvmBuildFileName), []byte(fmt.Sprintf("%d", build)), 0777)
}

View File

@ -32,6 +32,7 @@ func CreateScratchLayer(info DriverInfo, layerId, parentId string, parentLayerPa
func DeactivateLayer(info DriverInfo, id string) error { func DeactivateLayer(info DriverInfo, id string) error {
return wclayer.DeactivateLayer(context.Background(), layerPath(&info, id)) return wclayer.DeactivateLayer(context.Background(), layerPath(&info, id))
} }
func DestroyLayer(info DriverInfo, id string) error { func DestroyLayer(info DriverInfo, id string) error {
return wclayer.DestroyLayer(context.Background(), layerPath(&info, id)) return wclayer.DestroyLayer(context.Background(), layerPath(&info, id))
} }

View File

@ -25,6 +25,11 @@ func GetRootlessUID() int {
return os.Getuid() return os.Getuid()
} }
// GetRootlessGID returns the GID of the user in the parent userNS
func GetRootlessGID() int {
return os.Getgid()
}
// RootlessEnv returns the environment settings for the rootless containers // RootlessEnv returns the environment settings for the rootless containers
func RootlessEnv() []string { func RootlessEnv() []string {
return append(os.Environ(), UsernsEnvName+"=") return append(os.Environ(), UsernsEnvName+"=")

View File

@ -441,6 +441,16 @@ func GetRootlessUID() int {
return os.Getuid() return os.Getuid()
} }
// GetRootlessGID returns the GID of the user in the parent userNS
func GetRootlessGID() int {
gidEnv := getenv("_CONTAINERS_ROOTLESS_GID")
if gidEnv != "" {
u, _ := strconv.Atoi(gidEnv)
return u
}
return os.Getgid()
}
// RootlessEnv returns the environment settings for the rootless containers // RootlessEnv returns the environment settings for the rootless containers
func RootlessEnv() []string { func RootlessEnv() []string {
return append(os.Environ(), UsernsEnvName+"=done") return append(os.Environ(), UsernsEnvName+"=done")

View File

@ -25,6 +25,11 @@ func GetRootlessUID() int {
return os.Getuid() return os.Getuid()
} }
// GetRootlessGID returns the GID of the user in the parent userNS
func GetRootlessGID() int {
return os.Getgid()
}
// RootlessEnv returns the environment settings for the rootless containers // RootlessEnv returns the environment settings for the rootless containers
func RootlessEnv() []string { func RootlessEnv() []string {
return append(os.Environ(), UsernsEnvName+"=") return append(os.Environ(), UsernsEnvName+"=")

View File

@ -5,15 +5,19 @@ import (
"fmt" "fmt"
"io" "io"
"os" "os"
"runtime"
"strconv" "strconv"
"strings" "strings"
"sync"
"golang.org/x/sys/unix"
) )
// GetMountsFromReader retrieves a list of mounts from the // GetMountsFromReader retrieves a list of mounts from the
// reader provided, with an optional filter applied (use nil // reader provided, with an optional filter applied (use nil
// for no filter). This can be useful in tests or benchmarks // for no filter). This can be useful in tests or benchmarks
// that provide fake mountinfo data, or when a source other // that provide fake mountinfo data, or when a source other
// than /proc/self/mountinfo needs to be read from. // than /proc/thread-self/mountinfo needs to be read from.
// //
// This function is Linux-specific. // This function is Linux-specific.
func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) { func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
@ -127,8 +131,40 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) {
return out, nil return out, nil
} }
func parseMountTable(filter FilterFunc) ([]*Info, error) { var (
f, err := os.Open("/proc/self/mountinfo") haveProcThreadSelf bool
haveProcThreadSelfOnce sync.Once
)
func parseMountTable(filter FilterFunc) (_ []*Info, err error) {
haveProcThreadSelfOnce.Do(func() {
_, err := os.Stat("/proc/thread-self/mountinfo")
haveProcThreadSelf = err == nil
})
// We need to lock ourselves to the current OS thread in order to make sure
// that the thread referenced by /proc/thread-self stays alive until we
// finish parsing the file.
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var f *os.File
if haveProcThreadSelf {
f, err = os.Open("/proc/thread-self/mountinfo")
} else {
// On pre-3.17 kernels (such as CentOS 7), we don't have
// /proc/thread-self/ so we need to manually construct
// /proc/self/task/<tid>/ as a fallback.
f, err = os.Open("/proc/self/task/" + strconv.Itoa(unix.Gettid()) + "/mountinfo")
if os.IsNotExist(err) {
// If /proc/self/task/... failed, it means that our active pid
// namespace doesn't match the pid namespace of the /proc mount. In
// this case we just have to make do with /proc/self, since there
// is no other way of figuring out our tid in a parent pid
// namespace on pre-3.17 kernels.
f, err = os.Open("/proc/self/mountinfo")
}
}
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -158,10 +194,10 @@ func PidMountInfo(pid int) ([]*Info, error) {
// A few specific characters in mountinfo path entries (root and mountpoint) // A few specific characters in mountinfo path entries (root and mountpoint)
// are escaped using a backslash followed by a character's ascii code in octal. // are escaped using a backslash followed by a character's ascii code in octal.
// //
// space -- as \040 // space -- as \040
// tab (aka \t) -- as \011 // tab (aka \t) -- as \011
// newline (aka \n) -- as \012 // newline (aka \n) -- as \012
// backslash (aka \\) -- as \134 // backslash (aka \\) -- as \134
// //
// This function converts path from mountinfo back, i.e. it unescapes the above sequences. // This function converts path from mountinfo back, i.e. it unescapes the above sequences.
func unescape(path string) (string, error) { func unescape(path string) (string, error) {

6
vendor/modules.txt vendored
View File

@ -18,7 +18,7 @@ github.com/Microsoft/go-winio/internal/socket
github.com/Microsoft/go-winio/internal/stringbuffer github.com/Microsoft/go-winio/internal/stringbuffer
github.com/Microsoft/go-winio/pkg/guid github.com/Microsoft/go-winio/pkg/guid
github.com/Microsoft/go-winio/vhd github.com/Microsoft/go-winio/vhd
# github.com/Microsoft/hcsshim v0.12.0-rc.0 # github.com/Microsoft/hcsshim v0.12.0-rc.1
## explicit; go 1.18 ## explicit; go 1.18
github.com/Microsoft/hcsshim github.com/Microsoft/hcsshim
github.com/Microsoft/hcsshim/computestorage github.com/Microsoft/hcsshim/computestorage
@ -340,7 +340,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process github.com/containers/psgo/internal/process
# github.com/containers/storage v1.50.3-0.20231101112703-6e72f11598fb # github.com/containers/storage v1.50.3-0.20231108224651-a56f2b2fecfd
## explicit; go 1.19 ## explicit; go 1.19
github.com/containers/storage github.com/containers/storage
github.com/containers/storage/drivers github.com/containers/storage/drivers
@ -772,7 +772,7 @@ github.com/mitchellh/mapstructure
# github.com/moby/patternmatcher v0.5.0 # github.com/moby/patternmatcher v0.5.0
## explicit; go 1.19 ## explicit; go 1.19
github.com/moby/patternmatcher github.com/moby/patternmatcher
# github.com/moby/sys/mountinfo v0.6.2 # github.com/moby/sys/mountinfo v0.7.1
## explicit; go 1.16 ## explicit; go 1.16
github.com/moby/sys/mountinfo github.com/moby/sys/mountinfo
# github.com/moby/sys/sequential v0.5.0 # github.com/moby/sys/sequential v0.5.0