
RunWithPrivileges() will enable privileges will lock a thread, change privileges, and run the function passed in, within that thread. This allows us to limit the scope in which we enable privileges and avoids accidentally enabling privileges in threads that should never have them. Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
80 lines
3.0 KiB
Go
80 lines
3.0 KiB
Go
/*
|
|
Copyright The containerd Authors.
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package archive
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
|
|
"github.com/Microsoft/go-winio"
|
|
"github.com/Microsoft/hcsshim/pkg/ociwclayer"
|
|
)
|
|
|
|
// applyWindowsLayer applies a tar stream of an OCI style diff tar of a Windows layer
|
|
// See https://github.com/opencontainers/image-spec/blob/main/layer.md#applying-changesets
|
|
func applyWindowsLayer(ctx context.Context, root string, r io.Reader, options ApplyOptions) (size int64, err error) {
|
|
// It seems that in certain situations, like having the containerd root and state on a file system hosted on a
|
|
// mounted VHDX, we need SeSecurityPrivilege when opening a file with winio.ACCESS_SYSTEM_SECURITY. This happens
|
|
// in the base layer writer in hcsshim when adding a new file.
|
|
err = winio.RunWithPrivileges([]string{winio.SeSecurityPrivilege}, func() error {
|
|
var innerErr error
|
|
size, innerErr = ociwclayer.ImportLayerFromTar(ctx, r, root, options.Parents)
|
|
return innerErr
|
|
})
|
|
return
|
|
}
|
|
|
|
// AsWindowsContainerLayer indicates that the tar stream to apply is that of
|
|
// a Windows Container Layer. The caller must be holding SeBackupPrivilege and
|
|
// SeRestorePrivilege.
|
|
func AsWindowsContainerLayer() ApplyOpt {
|
|
return func(options *ApplyOptions) error {
|
|
options.applyFunc = applyWindowsLayer
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// writeDiffWindowsLayers writes a tar stream of the computed difference between the
|
|
// provided Windows layers
|
|
//
|
|
// Produces a tar using OCI style file markers for deletions. Deleted
|
|
// files will be prepended with the prefix ".wh.". This style is
|
|
// based off AUFS whiteouts.
|
|
// See https://github.com/opencontainers/image-spec/blob/main/layer.md
|
|
func writeDiffWindowsLayers(ctx context.Context, w io.Writer, _, layer string, options WriteDiffOptions) error {
|
|
return ociwclayer.ExportLayerToTar(ctx, w, layer, options.ParentLayers)
|
|
}
|
|
|
|
// AsWindowsContainerLayerPair indicates that the paths to diff are a pair of
|
|
// Windows Container Layers. The caller must be holding SeBackupPrivilege.
|
|
func AsWindowsContainerLayerPair() WriteDiffOpt {
|
|
return func(options *WriteDiffOptions) error {
|
|
options.writeDiffFunc = writeDiffWindowsLayers
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// WithParentLayers provides the Windows Container Layers that are the parents
|
|
// of the target (right-hand, "upper") layer, if any. The source (left-hand, "lower")
|
|
// layer passed to WriteDiff should be "" in this case.
|
|
func WithParentLayers(p []string) WriteDiffOpt {
|
|
return func(options *WriteDiffOptions) error {
|
|
options.ParentLayers = p
|
|
return nil
|
|
}
|
|
}
|