syscall_windows.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package system // import "github.com/docker/docker/pkg/system"
  2. import (
  3. "fmt"
  4. "syscall"
  5. "unsafe"
  6. "github.com/sirupsen/logrus"
  7. "golang.org/x/sys/windows"
  8. )
  9. const (
  10. OWNER_SECURITY_INFORMATION = 0x00000001
  11. GROUP_SECURITY_INFORMATION = 0x00000002
  12. DACL_SECURITY_INFORMATION = 0x00000004
  13. SACL_SECURITY_INFORMATION = 0x00000008
  14. LABEL_SECURITY_INFORMATION = 0x00000010
  15. ATTRIBUTE_SECURITY_INFORMATION = 0x00000020
  16. SCOPE_SECURITY_INFORMATION = 0x00000040
  17. PROCESS_TRUST_LABEL_SECURITY_INFORMATION = 0x00000080
  18. ACCESS_FILTER_SECURITY_INFORMATION = 0x00000100
  19. BACKUP_SECURITY_INFORMATION = 0x00010000
  20. PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000
  21. PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000
  22. UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000
  23. UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000
  24. )
  25. const (
  26. SE_UNKNOWN_OBJECT_TYPE = iota
  27. SE_FILE_OBJECT
  28. SE_SERVICE
  29. SE_PRINTER
  30. SE_REGISTRY_KEY
  31. SE_LMSHARE
  32. SE_KERNEL_OBJECT
  33. SE_WINDOW_OBJECT
  34. SE_DS_OBJECT
  35. SE_DS_OBJECT_ALL
  36. SE_PROVIDER_DEFINED_OBJECT
  37. SE_WMIGUID_OBJECT
  38. SE_REGISTRY_WOW64_32KEY
  39. )
  40. const (
  41. SeTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege"
  42. )
  43. const (
  44. ContainerAdministratorSidString = "S-1-5-93-2-1"
  45. ContainerUserSidString = "S-1-5-93-2-2"
  46. )
  47. var (
  48. ntuserApiset = windows.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
  49. modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
  50. procGetVersionExW = modkernel32.NewProc("GetVersionExW")
  51. procSetNamedSecurityInfo = modadvapi32.NewProc("SetNamedSecurityInfoW")
  52. procGetSecurityDescriptorDacl = modadvapi32.NewProc("GetSecurityDescriptorDacl")
  53. )
  54. // OSVersion is a wrapper for Windows version information
  55. // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx
  56. type OSVersion struct {
  57. Version uint32
  58. MajorVersion uint8
  59. MinorVersion uint8
  60. Build uint16
  61. }
  62. // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
  63. type osVersionInfoEx struct {
  64. OSVersionInfoSize uint32
  65. MajorVersion uint32
  66. MinorVersion uint32
  67. BuildNumber uint32
  68. PlatformID uint32
  69. CSDVersion [128]uint16
  70. ServicePackMajor uint16
  71. ServicePackMinor uint16
  72. SuiteMask uint16
  73. ProductType byte
  74. Reserve byte
  75. }
  76. // GetOSVersion gets the operating system version on Windows. Note that
  77. // docker.exe must be manifested to get the correct version information.
  78. func GetOSVersion() OSVersion {
  79. var err error
  80. osv := OSVersion{}
  81. osv.Version, err = windows.GetVersion()
  82. if err != nil {
  83. // GetVersion never fails.
  84. panic(err)
  85. }
  86. osv.MajorVersion = uint8(osv.Version & 0xFF)
  87. osv.MinorVersion = uint8(osv.Version >> 8 & 0xFF)
  88. osv.Build = uint16(osv.Version >> 16)
  89. return osv
  90. }
  91. func (osv OSVersion) ToString() string {
  92. return fmt.Sprintf("%d.%d.%d", osv.MajorVersion, osv.MinorVersion, osv.Build)
  93. }
  94. // IsWindowsClient returns true if the SKU is client
  95. // @engine maintainers - this function should not be removed or modified as it
  96. // is used to enforce licensing restrictions on Windows.
  97. func IsWindowsClient() bool {
  98. osviex := &osVersionInfoEx{OSVersionInfoSize: 284}
  99. r1, _, err := procGetVersionExW.Call(uintptr(unsafe.Pointer(osviex)))
  100. if r1 == 0 {
  101. logrus.Warnf("GetVersionExW failed - assuming server SKU: %v", err)
  102. return false
  103. }
  104. const verNTWorkstation = 0x00000001
  105. return osviex.ProductType == verNTWorkstation
  106. }
  107. // Unmount is a platform-specific helper function to call
  108. // the unmount syscall. Not supported on Windows
  109. func Unmount(dest string) error {
  110. return nil
  111. }
  112. // CommandLineToArgv wraps the Windows syscall to turn a commandline into an argument array.
  113. func CommandLineToArgv(commandLine string) ([]string, error) {
  114. var argc int32
  115. argsPtr, err := windows.UTF16PtrFromString(commandLine)
  116. if err != nil {
  117. return nil, err
  118. }
  119. argv, err := windows.CommandLineToArgv(argsPtr, &argc)
  120. if err != nil {
  121. return nil, err
  122. }
  123. defer windows.LocalFree(windows.Handle(uintptr(unsafe.Pointer(argv))))
  124. newArgs := make([]string, argc)
  125. for i, v := range (*argv)[:argc] {
  126. newArgs[i] = string(windows.UTF16ToString((*v)[:]))
  127. }
  128. return newArgs, nil
  129. }
  130. // HasWin32KSupport determines whether containers that depend on win32k can
  131. // run on this machine. Win32k is the driver used to implement windowing.
  132. func HasWin32KSupport() bool {
  133. // For now, check for ntuser API support on the host. In the future, a host
  134. // may support win32k in containers even if the host does not support ntuser
  135. // APIs.
  136. return ntuserApiset.Load() == nil
  137. }
  138. func SetNamedSecurityInfo(objectName *uint16, objectType uint32, securityInformation uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *byte, sacl *byte) (result error) {
  139. r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfo.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(sidOwner)), uintptr(unsafe.Pointer(sidGroup)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0)
  140. if r0 != 0 {
  141. result = syscall.Errno(r0)
  142. }
  143. return
  144. }
  145. func GetSecurityDescriptorDacl(securityDescriptor *byte, daclPresent *uint32, dacl **byte, daclDefaulted *uint32) (result error) {
  146. r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(securityDescriptor)), uintptr(unsafe.Pointer(daclPresent)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclDefaulted)), 0, 0)
  147. if r1 == 0 {
  148. if e1 != 0 {
  149. result = syscall.Errno(e1)
  150. } else {
  151. result = syscall.EINVAL
  152. }
  153. }
  154. return
  155. }