package dockerfile // import "github.com/docker/docker/builder/dockerfile" import ( "fmt" "os" "path/filepath" "strings" "github.com/Microsoft/go-winio" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/pkg/reexec" "github.com/docker/docker/pkg/system" "github.com/pkg/errors" "golang.org/x/sys/windows" ) var pathBlacklist = map[string]bool{ "c:\\": true, "c:\\windows": true, } func init() { reexec.Register("windows-fix-permissions", fixPermissionsReexec) } func fixPermissions(source, destination string, identity idtools.Identity, _ bool) error { if identity.SID == "" { return nil } cmd := reexec.Command("windows-fix-permissions", source, destination, identity.SID) output, err := cmd.CombinedOutput() return errors.Wrapf(err, "failed to exec windows-fix-permissions: %s", output) } func fixPermissionsReexec() { err := fixPermissionsWindows(os.Args[1], os.Args[2], os.Args[3]) if err != nil { fmt.Fprint(os.Stderr, err) os.Exit(1) } } func fixPermissionsWindows(source, destination, SID string) error { privileges := []string{winio.SeRestorePrivilege, system.SeTakeOwnershipPrivilege} err := winio.EnableProcessPrivileges(privileges) if err != nil { return err } defer winio.DisableProcessPrivileges(privileges) sid, err := windows.StringToSid(SID) if err != nil { return err } // Owners on *nix have read/write/delete/read control and write DAC. // Add an ACE that grants this to the user/group specified with the // chown option. Currently Windows is not honoring the owner change, // however, they are aware of this and it should be fixed at some // point. sddlString := system.SddlAdministratorsLocalSystem sddlString += "(A;OICI;GRGWGXRCWDSD;;;" + SID + ")" securityDescriptor, err := winio.SddlToSecurityDescriptor(sddlString) if err != nil { return err } var daclPresent uint32 var daclDefaulted uint32 var dacl *byte err = system.GetSecurityDescriptorDacl(&securityDescriptor[0], &daclPresent, &dacl, &daclDefaulted) if err != nil { return err } return system.SetNamedSecurityInfo(windows.StringToUTF16Ptr(destination), system.SE_FILE_OBJECT, system.OWNER_SECURITY_INFORMATION|system.DACL_SECURITY_INFORMATION, sid, nil, dacl, nil) } func validateCopySourcePath(imageSource *imageMount, origPath, platform string) error { // validate windows paths from other images + LCOW if imageSource == nil || platform != "windows" { return nil } origPath = filepath.FromSlash(origPath) p := strings.ToLower(filepath.Clean(origPath)) if !filepath.IsAbs(p) { if filepath.VolumeName(p) != "" { if p[len(p)-2:] == ":." { // case where clean returns weird c:. paths p = p[:len(p)-1] } p += "\\" } else { p = filepath.Join("c:\\", p) } } if _, blacklisted := pathBlacklist[p]; blacklisted { return errors.New("copy from c:\\ or c:\\windows is not allowed on windows") } return nil }