Merge pull request #28002 from Microsoft/jjh/noreexec
Windows: Allow a no-reexec option for importLayer
This commit is contained in:
commit
5e3d777401
3 changed files with 82 additions and 55 deletions
|
@ -45,12 +45,20 @@ var (
|
|||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG1": "bcd.log1.bak",
|
||||
"UtilityVM/Files/EFI/Microsoft/Boot/BCD.LOG2": "bcd.log2.bak",
|
||||
}
|
||||
noreexec = false
|
||||
)
|
||||
|
||||
// init registers the windows graph drivers to the register.
|
||||
func init() {
|
||||
graphdriver.Register("windowsfilter", InitFilter)
|
||||
reexec.Register("docker-windows-write-layer", writeLayer)
|
||||
// DOCKER_WINDOWSFILTER_NOREEXEC allows for inline processing which makes
|
||||
// debugging issues in the re-exec codepath significantly easier.
|
||||
if os.Getenv("DOCKER_WINDOWSFILTER_NOREEXEC") != "" {
|
||||
logrus.Warnf("WindowsGraphDriver is set to not re-exec. This is intended for debugging purposes only.")
|
||||
noreexec = true
|
||||
} else {
|
||||
reexec.Register("docker-windows-write-layer", writeLayerReexec)
|
||||
}
|
||||
}
|
||||
|
||||
type checker struct {
|
||||
|
@ -658,63 +666,73 @@ func writeLayerFromTar(r io.Reader, w hcsshim.LayerWriter, root string) (int64,
|
|||
|
||||
// importLayer adds a new layer to the tag and graph store based on the given data.
|
||||
func (d *Driver) importLayer(id string, layerData io.Reader, parentLayerPaths []string) (size int64, err error) {
|
||||
cmd := reexec.Command(append([]string{"docker-windows-write-layer", d.info.HomeDir, id}, parentLayerPaths...)...)
|
||||
output := bytes.NewBuffer(nil)
|
||||
cmd.Stdin = layerData
|
||||
cmd.Stdout = output
|
||||
cmd.Stderr = output
|
||||
if !noreexec {
|
||||
cmd := reexec.Command(append([]string{"docker-windows-write-layer", d.info.HomeDir, id}, parentLayerPaths...)...)
|
||||
output := bytes.NewBuffer(nil)
|
||||
cmd.Stdin = layerData
|
||||
cmd.Stdout = output
|
||||
cmd.Stderr = output
|
||||
|
||||
if err = cmd.Start(); err != nil {
|
||||
return
|
||||
if err = cmd.Start(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = cmd.Wait(); err != nil {
|
||||
return 0, fmt.Errorf("re-exec error: %v: output: %s", err, output)
|
||||
}
|
||||
|
||||
return strconv.ParseInt(output.String(), 10, 64)
|
||||
}
|
||||
|
||||
if err = cmd.Wait(); err != nil {
|
||||
return 0, fmt.Errorf("re-exec error: %v: output: %s", err, output)
|
||||
}
|
||||
|
||||
return strconv.ParseInt(output.String(), 10, 64)
|
||||
return writeLayer(layerData, d.info.HomeDir, id, parentLayerPaths...)
|
||||
}
|
||||
|
||||
// writeLayer is the re-exec entry point for writing a layer from a tar file
|
||||
func writeLayer() {
|
||||
home := os.Args[1]
|
||||
id := os.Args[2]
|
||||
parentLayerPaths := os.Args[3:]
|
||||
|
||||
err := func() error {
|
||||
err := winio.EnableProcessPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info := hcsshim.DriverInfo{
|
||||
Flavour: filterDriver,
|
||||
HomeDir: home,
|
||||
}
|
||||
|
||||
w, err := hcsshim.NewLayerWriter(info, id, parentLayerPaths)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
size, err := writeLayerFromTar(os.Stdin, w, filepath.Join(home, id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprint(os.Stdout, size)
|
||||
return nil
|
||||
}()
|
||||
|
||||
// writeLayerReexec is the re-exec entry point for writing a layer from a tar file
|
||||
func writeLayerReexec() {
|
||||
size, err := writeLayer(os.Stdin, os.Args[1], os.Args[2], os.Args[3:]...)
|
||||
if err != nil {
|
||||
fmt.Fprint(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Fprint(os.Stdout, size)
|
||||
}
|
||||
|
||||
// writeLayer writes a layer from a tar file.
|
||||
func writeLayer(layerData io.Reader, home string, id string, parentLayerPaths ...string) (int64, error) {
|
||||
err := winio.EnableProcessPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if noreexec {
|
||||
defer func() {
|
||||
if err := winio.DisableProcessPrivileges([]string{winio.SeBackupPrivilege, winio.SeRestorePrivilege}); err != nil {
|
||||
// This should never happen, but just in case when in debugging mode.
|
||||
// See https://github.com/docker/docker/pull/28002#discussion_r86259241 for rationale.
|
||||
panic("Failed to disabled process privileges while in non re-exec mode")
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
info := hcsshim.DriverInfo{
|
||||
Flavour: filterDriver,
|
||||
HomeDir: home,
|
||||
}
|
||||
|
||||
w, err := hcsshim.NewLayerWriter(info, id, parentLayerPaths)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
size, err := writeLayerFromTar(layerData, w, filepath.Join(home, id))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = w.Close()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return size, nil
|
||||
}
|
||||
|
||||
// resolveID computes the layerID information based on the given id.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# the following lines are in sorted order, FYI
|
||||
github.com/Azure/go-ansiterm 388960b655244e76e24c75f48631564eaefade62
|
||||
github.com/Microsoft/hcsshim v0.5.7
|
||||
github.com/Microsoft/go-winio v0.3.5
|
||||
github.com/Microsoft/go-winio v0.3.6
|
||||
github.com/Sirupsen/logrus f76d643702a30fbffecdfe50831e11881c96ceb3 https://github.com/aaronlehmann/logrus
|
||||
github.com/davecgh/go-spew 6d212800a42e8ab5c146b8ace3490ee17e5225f9
|
||||
github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a
|
||||
|
|
17
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
17
vendor/github.com/Microsoft/go-winio/privilege.go
generated
vendored
|
@ -83,7 +83,7 @@ func RunWithPrivileges(names []string, fn func() error) error {
|
|||
return err
|
||||
}
|
||||
defer releaseThreadToken(token)
|
||||
err = adjustPrivileges(token, privileges)
|
||||
err = adjustPrivileges(token, privileges, SE_PRIVILEGE_ENABLED)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -110,6 +110,15 @@ func mapPrivileges(names []string) ([]uint64, error) {
|
|||
|
||||
// EnableProcessPrivileges enables privileges globally for the process.
|
||||
func EnableProcessPrivileges(names []string) error {
|
||||
return enableDisableProcessPrivilege(names, SE_PRIVILEGE_ENABLED)
|
||||
}
|
||||
|
||||
// DisableProcessPrivileges disables privileges globally for the process.
|
||||
func DisableProcessPrivileges(names []string) error {
|
||||
return enableDisableProcessPrivilege(names, 0)
|
||||
}
|
||||
|
||||
func enableDisableProcessPrivilege(names []string, action uint32) error {
|
||||
privileges, err := mapPrivileges(names)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -123,15 +132,15 @@ func EnableProcessPrivileges(names []string) error {
|
|||
}
|
||||
|
||||
defer token.Close()
|
||||
return adjustPrivileges(token, privileges)
|
||||
return adjustPrivileges(token, privileges, action)
|
||||
}
|
||||
|
||||
func adjustPrivileges(token windows.Token, privileges []uint64) error {
|
||||
func adjustPrivileges(token windows.Token, privileges []uint64, action uint32) error {
|
||||
var b bytes.Buffer
|
||||
binary.Write(&b, binary.LittleEndian, uint32(len(privileges)))
|
||||
for _, p := range privileges {
|
||||
binary.Write(&b, binary.LittleEndian, p)
|
||||
binary.Write(&b, binary.LittleEndian, uint32(SE_PRIVILEGE_ENABLED))
|
||||
binary.Write(&b, binary.LittleEndian, action)
|
||||
}
|
||||
prevState := make([]byte, b.Len())
|
||||
reqSize := uint32(0)
|
||||
|
|
Loading…
Add table
Reference in a new issue