github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/builder/dockerfile/copy_windows.go (about) 1 package dockerfile // import "github.com/Prakhar-Agarwal-byte/moby/builder/dockerfile" 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 9 winio "github.com/Microsoft/go-winio" 10 "github.com/Prakhar-Agarwal-byte/moby/pkg/idtools" 11 "github.com/Prakhar-Agarwal-byte/moby/pkg/reexec" 12 "github.com/Prakhar-Agarwal-byte/moby/pkg/system" 13 "github.com/pkg/errors" 14 "golang.org/x/sys/windows" 15 ) 16 17 var pathDenyList = map[string]bool{ 18 `c:\`: true, 19 `c:\windows`: true, 20 } 21 22 func init() { 23 reexec.Register("windows-fix-permissions", fixPermissionsReexec) 24 } 25 26 func fixPermissions(source, destination string, identity idtools.Identity, _ bool) error { 27 if identity.SID == "" { 28 return nil 29 } 30 31 cmd := reexec.Command("windows-fix-permissions", source, destination, identity.SID) 32 output, err := cmd.CombinedOutput() 33 34 return errors.Wrapf(err, "failed to exec windows-fix-permissions: %s", output) 35 } 36 37 func fixPermissionsReexec() { 38 err := fixPermissionsWindows(os.Args[1], os.Args[2], os.Args[3]) 39 if err != nil { 40 fmt.Fprint(os.Stderr, err) 41 os.Exit(1) 42 } 43 } 44 45 func fixPermissionsWindows(source, destination, SID string) error { 46 privileges := []string{winio.SeRestorePrivilege, idtools.SeTakeOwnershipPrivilege} 47 48 err := winio.EnableProcessPrivileges(privileges) 49 if err != nil { 50 return err 51 } 52 53 defer winio.DisableProcessPrivileges(privileges) 54 55 sid, err := windows.StringToSid(SID) 56 if err != nil { 57 return err 58 } 59 60 // Owners on *nix have read/write/delete/read control and write DAC. 61 // Add an ACE that grants this to the user/group specified with the 62 // chown option. Currently Windows is not honoring the owner change, 63 // however, they are aware of this and it should be fixed at some 64 // point. 65 66 sddlString := system.SddlAdministratorsLocalSystem 67 sddlString += "(A;OICI;GRGWGXRCWDSD;;;" + SID + ")" 68 69 securityDescriptor, err := windows.SecurityDescriptorFromString(sddlString) 70 if err != nil { 71 return err 72 } 73 74 dacl, _, err := securityDescriptor.DACL() 75 if err != nil { 76 return err 77 } 78 79 return windows.SetNamedSecurityInfo(destination, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION|windows.DACL_SECURITY_INFORMATION, sid, nil, dacl, nil) 80 } 81 82 // normalizeDest normalises the destination of a COPY/ADD command in a 83 // platform semantically consistent way. 84 func normalizeDest(workingDir, requested string) (string, error) { 85 dest := filepath.FromSlash(requested) 86 endsInSlash := strings.HasSuffix(dest, string(os.PathSeparator)) 87 88 // We are guaranteed that the working directory is already consistent, 89 // However, Windows also has, for now, the limitation that ADD/COPY can 90 // only be done to the system drive, not any drives that might be present 91 // as a result of a bind mount. 92 // 93 // So... if the path requested is Linux-style absolute (/foo or \\foo), 94 // we assume it is the system drive. If it is a Windows-style absolute 95 // (DRIVE:\\foo), error if DRIVE is not C. And finally, ensure we 96 // strip any configured working directories drive letter so that it 97 // can be subsequently legitimately converted to a Windows volume-style 98 // pathname. 99 100 // Not a typo - filepath.IsAbs, not system.IsAbs on this next check as 101 // we only want to validate where the DriveColon part has been supplied. 102 if filepath.IsAbs(dest) { 103 if strings.ToUpper(string(dest[0])) != "C" { 104 return "", fmt.Errorf("Windows does not support destinations not on the system drive (C:)") 105 } 106 dest = dest[2:] // Strip the drive letter 107 } 108 109 // Cannot handle relative where WorkingDir is not the system drive. 110 if len(workingDir) > 0 { 111 if ((len(workingDir) > 1) && !system.IsAbs(workingDir[2:])) || (len(workingDir) == 1) { 112 return "", fmt.Errorf("Current WorkingDir %s is not platform consistent", workingDir) 113 } 114 if !system.IsAbs(dest) { 115 if string(workingDir[0]) != "C" { 116 return "", fmt.Errorf("Windows does not support relative paths when WORKDIR is not the system drive") 117 } 118 dest = filepath.Join(string(os.PathSeparator), workingDir[2:], dest) 119 // Make sure we preserve any trailing slash 120 if endsInSlash { 121 dest += string(os.PathSeparator) 122 } 123 } 124 } 125 return dest, nil 126 } 127 128 func containsWildcards(name string) bool { 129 for i := 0; i < len(name); i++ { 130 ch := name[i] 131 if ch == '*' || ch == '?' || ch == '[' { 132 return true 133 } 134 } 135 return false 136 } 137 138 func validateCopySourcePath(imageSource *imageMount, origPath string) error { 139 if imageSource == nil { 140 return nil 141 } 142 origPath = filepath.FromSlash(origPath) 143 p := strings.ToLower(filepath.Clean(origPath)) 144 if !filepath.IsAbs(p) { 145 if filepath.VolumeName(p) != "" { 146 if p[len(p)-2:] == ":." { // case where clean returns weird c:. paths 147 p = p[:len(p)-1] 148 } 149 p += `\` 150 } else { 151 p = filepath.Join(`c:\`, p) 152 } 153 } 154 if _, ok := pathDenyList[p]; ok { 155 return errors.New(`copy from c:\ or c:\windows is not allowed on windows`) 156 } 157 return nil 158 }