From a7d59eb1e71685edb76d3aa59df4f24c864ee285 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 7 May 2019 20:34:01 +0200 Subject: service: give process elevated security attributes plus logon session ID with minimal permissions --- service/errors.go | 3 - service/mksyscall.go | 2 +- service/securityapi.go | 176 +++++++++++++++++++++++++++++++++++++++----- service/service_manager.go | 27 ++----- service/zsyscall_windows.go | 145 +++++++++++++++++++++++++++++++++++- 5 files changed, 311 insertions(+), 42 deletions(-) diff --git a/service/errors.go b/service/errors.go index eb31bb4e..670c3305 100644 --- a/service/errors.go +++ b/service/errors.go @@ -26,7 +26,6 @@ const ( ErrorBindSocketsToDefaultRoutes ErrorSetNetConfig ErrorDetermineExecutablePath - ErrorCreateSecurityDescriptor ErrorOpenNULFile ErrorTrackTunnels ErrorEnumerateSessions @@ -59,8 +58,6 @@ func (e Error) Error() string { return "Unable to bind sockets to default route" case ErrorSetNetConfig: return "Unable to set interface addresses, routes, dns, and/or adapter settings" - case ErrorCreateSecurityDescriptor: - return "Unable to determine security descriptor" case ErrorOpenNULFile: return "Unable to open NUL file" case ErrorTrackTunnels: diff --git a/service/mksyscall.go b/service/mksyscall.go index ccc4053e..417a99fb 100644 --- a/service/mksyscall.go +++ b/service/mksyscall.go @@ -5,4 +5,4 @@ package service -//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go service_manager.go tunneltracker.go +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go securityapi.go tunneltracker.go diff --git a/service/securityapi.go b/service/securityapi.go index 6373fd7c..b0de8604 100644 --- a/service/securityapi.go +++ b/service/securityapi.go @@ -7,7 +7,9 @@ package service import ( "errors" + "fmt" "golang.org/x/sys/windows" + "runtime" "syscall" "unicode/utf16" "unsafe" @@ -51,12 +53,65 @@ type wtsSessionInfo struct { const ( SE_KERNEL_OBJECT = 6 - DACL_SECURITY_INFORMATION = 4 - ATTRIBUTE_SECURITY_INFORMATION = 16 + SE_GROUP_LOGON_ID = 0xC0000000 + SE_GROUP_ENABLED = 0x00000004 + SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010 + + ACL_REVISION = 2 + + PROCESS_TERMINATE = 0x0001 + PROCESS_CREATE_THREAD = 0x0002 + PROCESS_SET_SESSIONID = 0x0004 + PROCESS_VM_OPERATION = 0x0008 + PROCESS_VM_READ = 0x0010 + PROCESS_VM_WRITE = 0x0020 + PROCESS_DUP_HANDLE = 0x0040 + PROCESS_CREATE_PROCESS = 0x0080 + PROCESS_SET_QUOTA = 0x0100 + PROCESS_SET_INFORMATION = 0x0200 + PROCESS_QUERY_INFORMATION = 0x0400 + PROCESS_SUSPEND_RESUME = 0x0800 + PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 + + OWNER_SECURITY_INFORMATION = 0x00000001 + GROUP_SECURITY_INFORMATION = 0x00000002 + DACL_SECURITY_INFORMATION = 0x00000004 + SACL_SECURITY_INFORMATION = 0x00000008 + LABEL_SECURITY_INFORMATION = 0x00000010 + ATTRIBUTE_SECURITY_INFORMATION = 0x00000020 + SCOPE_SECURITY_INFORMATION = 0x00000040 + BACKUP_SECURITY_INFORMATION = 0x00010000 + PROTECTED_DACL_SECURITY_INFORMATION = 0x80000000 + PROTECTED_SACL_SECURITY_INFORMATION = 0x40000000 + UNPROTECTED_DACL_SECURITY_INFORMATION = 0x20000000 + UNPROTECTED_SACL_SECURITY_INFORMATION = 0x10000000 + + AclRevisionInformation = 1 + AclSizeInformation = 2 ) -//sys getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo +type ACL_SIZE_INFORMATION struct { + aceCount uint32 + aclBytesInUse uint32 + aclBytesFree uint32 +} +type ACE_HEADER struct { + aceType byte + aceFlags byte + aceSize uint16 +} + +//sys getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, owner *uintptr, group *uintptr, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo //sys getSecurityDescriptorLength(securityDescriptor uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength +//sys addAccessAllowedAce(acl uintptr, aceRevision uint32, accessmask uint32, sid *windows.SID) (err error) = advapi32.AddAccessAllowedAce +//sys setSecurityDescriptorDacl(securityDescriptor uintptr, daclPresent bool, dacl uintptr, defaulted bool) (err error) = advapi32.SetSecurityDescriptorDacl +//sys setSecurityDescriptorSacl(securityDescriptor uintptr, saclPresent bool, sacl uintptr, defaulted bool) (err error) = advapi32.SetSecurityDescriptorSacl +//sys getAclInformation(acl uintptr, info unsafe.Pointer, len uint32, infoclass uint32) (err error) = advapi32.GetAclInformation +//sys getAce(acl uintptr, index uint32, ace *uintptr) (err error) = advapi32.GetAce +//sys addAce(acl uintptr, revision uint32, index uint32, ace uintptr, lenAce uint32) (err error) = advapi32.AddAce +//sys initializeAcl(acl uintptr, len uint32, revision uint32) (err error) = advapi32.InitializeAcl +//sys makeAbsoluteSd(selfRelativeSecurityDescriptor uintptr, absoluteSecurityDescriptor uintptr, absoluteSecurityDescriptorSize *uint32, dacl uintptr, daclSize *uint32, sacl uintptr, saclSize *uint32, owner uintptr, ownerSize *uint32, primaryGroup uintptr, primaryGroupSize *uint32) (err error) = advapi32.MakeAbsoluteSD +//sys makeSelfRelativeSd(absoluteSecurityDescriptor uintptr, relativeSecurityDescriptor uintptr, relativeSecurityDescriptorSize *uint32) (err error) = advapi32.MakeSelfRelativeSD //sys createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock //sys destroyEnvironmentBlock(block uintptr) (err error) = userenv.DestroyEnvironmentBlock @@ -115,8 +170,6 @@ func getElevatedToken(token windows.Token) (windows.Token, error) { } func tokenIsMemberOfBuiltInAdministrator(token windows.Token) bool { - //TODO: SECURITY CRITICIAL! - //TODO: Isn't it better to use an impersonation token or userToken.IsMember instead? adminSid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid) if err != nil { return false @@ -125,33 +178,122 @@ func tokenIsMemberOfBuiltInAdministrator(token windows.Token) bool { if err != nil { return false } - p := unsafe.Pointer(&gs.Groups[0]) - groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(p)[:gs.GroupCount] + groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(unsafe.Pointer(&gs.Groups[0]))[:gs.GroupCount] isAdmin := false for _, g := range groups { - if windows.EqualSid(g.Sid, adminSid) { + if (g.Attributes&SE_GROUP_USE_FOR_DENY_ONLY != 0 || g.Attributes&SE_GROUP_ENABLED != 0) && windows.EqualSid(g.Sid, adminSid) { isAdmin = true break } } + runtime.KeepAlive(gs) return isAdmin } -func getCurrentSecurityAttributes() (*syscall.SecurityAttributes, error) { - currentProcess, err := windows.GetCurrentProcess() +func sliceToSecurityAttributes(sa []byte) *syscall.SecurityAttributes { + return &syscall.SecurityAttributes{ + Length: uint32(len(sa)), + SecurityDescriptor: uintptr(unsafe.Pointer(&sa[0])), + } +} + +func getSecurityAttributes(mainToken windows.Token, tokenThatHasLogonSession windows.Token) ([]byte, error) { + gs, err := tokenThatHasLogonSession.GetTokenGroups() + if err != nil { + return nil, err + } + var logonSid *windows.SID + groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(unsafe.Pointer(&gs.Groups[0]))[:gs.GroupCount] + for _, g := range groups { + if g.Attributes&SE_GROUP_LOGON_ID != 0 && g.Attributes&SE_GROUP_ENABLED != 0 { + logonSid = g.Sid + break + } + } + if logonSid == nil { + return nil, errors.New("Unable to find logon SID") + } + + var originalSecurityDescriptor uintptr + err = getSecurityInfo(windows.Handle(mainToken), SE_KERNEL_OBJECT, ATTRIBUTE_SECURITY_INFORMATION|LABEL_SECURITY_INFORMATION|SCOPE_SECURITY_INFORMATION|OWNER_SECURITY_INFORMATION|GROUP_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, nil, nil, nil, nil, &originalSecurityDescriptor) + if err != nil { + return nil, err + } + var ( + absoluteSecurityDescriptorSize uint32 + daclSize uint32 + saclSize uint32 + ownerSize uint32 + primaryGroupSize uint32 + ) + err = makeAbsoluteSd(originalSecurityDescriptor, 0, &absoluteSecurityDescriptorSize, 0, &daclSize, 0, &saclSize, 0, &ownerSize, 0, &primaryGroupSize) + if err != windows.ERROR_INSUFFICIENT_BUFFER { + windows.LocalFree(windows.Handle(originalSecurityDescriptor)) + return nil, fmt.Errorf("Expected insufficient buffer from MakeAbsoluteSd, but got: %v", err) + } + absoluteSecurityDescriptor := make([]byte, absoluteSecurityDescriptorSize) + dacl := make([]byte, daclSize) + sacl := make([]byte, saclSize) + owner := make([]byte, ownerSize) + primaryGroup := make([]byte, primaryGroupSize) + err = makeAbsoluteSd(originalSecurityDescriptor, uintptr(unsafe.Pointer(&absoluteSecurityDescriptor[0])), &absoluteSecurityDescriptorSize, uintptr(unsafe.Pointer(&dacl[0])), &daclSize, uintptr(unsafe.Pointer(&sacl[0])), &saclSize, uintptr(unsafe.Pointer(&owner[0])), &ownerSize, uintptr(unsafe.Pointer(&primaryGroup[0])), &primaryGroupSize) + if err != nil { + windows.LocalFree(windows.Handle(originalSecurityDescriptor)) + return nil, err + } + windows.LocalFree(windows.Handle(originalSecurityDescriptor)) + + var daclInfo ACL_SIZE_INFORMATION + err = getAclInformation(uintptr(unsafe.Pointer(&dacl[0])), unsafe.Pointer(&daclInfo), uint32(unsafe.Sizeof(daclInfo)), AclSizeInformation) if err != nil { return nil, err } - securityAttributes := &syscall.SecurityAttributes{} - err = getSecurityInfo(currentProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, nil, nil, &securityAttributes.SecurityDescriptor) + newDacl := make([]byte, daclInfo.aclBytesInUse*2) + err = initializeAcl(uintptr(unsafe.Pointer(&newDacl[0])), uint32(len(newDacl)), ACL_REVISION) if err != nil { return nil, err } - windows.LocalFree(windows.Handle(securityAttributes.SecurityDescriptor)) - securityAttributes.Length = getSecurityDescriptorLength(securityAttributes.SecurityDescriptor) - if securityAttributes.Length == 0 { - windows.LocalFree(windows.Handle(securityAttributes.SecurityDescriptor)) + var ace uintptr + for i := uint32(0); i < daclInfo.aceCount; i++ { + err = getAce(uintptr(unsafe.Pointer(&dacl[0])), i, &ace) + if err != nil { + return nil, err + } + err = addAce(uintptr(unsafe.Pointer(&newDacl[0])), ACL_REVISION, ^uint32(0), ace, uint32(((*ACE_HEADER)(unsafe.Pointer(ace))).aceSize)) + if err != nil { + return nil, err + } + } + runtime.KeepAlive(dacl) + err = addAccessAllowedAce(uintptr(unsafe.Pointer(&newDacl[0])), ACL_REVISION, PROCESS_QUERY_LIMITED_INFORMATION, logonSid) + if err != nil { return nil, err } - return securityAttributes, nil + runtime.KeepAlive(gs) + err = setSecurityDescriptorDacl(uintptr(unsafe.Pointer(&absoluteSecurityDescriptor[0])), true, uintptr(unsafe.Pointer(&newDacl[0])), false) + if err != nil { + return nil, err + } + //TODO: This should not be required!! But right now we can't give the process the high integrity SACL, which is unfortunate. So we unset it. + err = setSecurityDescriptorSacl(uintptr(unsafe.Pointer(&absoluteSecurityDescriptor[0])), false, 0, true) + if err != nil { + return nil, err + } + var selfRelativeSecurityDescriptorSize uint32 + err = makeSelfRelativeSd(uintptr(unsafe.Pointer(&absoluteSecurityDescriptor[0])), 0, &selfRelativeSecurityDescriptorSize) + if err != windows.ERROR_INSUFFICIENT_BUFFER { + return nil, fmt.Errorf("Expected insufficient buffer from MakeSelfRelativeSd, but got: %v", err) + } + relativeSecurityDescriptor := make([]byte, selfRelativeSecurityDescriptorSize) + err = makeSelfRelativeSd(uintptr(unsafe.Pointer(&absoluteSecurityDescriptor[0])), uintptr(unsafe.Pointer(&relativeSecurityDescriptor[0])), &selfRelativeSecurityDescriptorSize) + if err != nil { + return nil, err + } + runtime.KeepAlive(absoluteSecurityDescriptor) + runtime.KeepAlive(newDacl) + runtime.KeepAlive(sacl) + runtime.KeepAlive(owner) + runtime.KeepAlive(primaryGroup) + + return relativeSecurityDescriptor, nil } diff --git a/service/service_manager.go b/service/service_manager.go index aae11daf..2862c729 100644 --- a/service/service_manager.go +++ b/service/service_manager.go @@ -54,12 +54,6 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest serviceError = ErrorDetermineExecutablePath return } - securityAttributes, err := getCurrentSecurityAttributes() - if err != nil { - serviceError = ErrorCreateSecurityDescriptor - return - } - defer windows.LocalFree(windows.Handle(securityAttributes.SecurityDescriptor)) devNull, err := os.OpenFile(os.DevNull, os.O_RDWR, 0) if err != nil { @@ -124,6 +118,11 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest log.Printf("Unable to determine elevated environment: %v", err) return } + securityAttributes, err := getSecurityAttributes(userTokenInfo.elevatedToken, userToken) + if err != nil { + log.Printf("Unable to extract security attributes from elevated token and combine them with SID from user token: %v", err) + return + } for { if stoppingManager { return @@ -153,19 +152,9 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest log.Printf("Starting UI process for user: '%s@%s'", username, domain) attr := &os.ProcAttr{ Sys: &syscall.SysProcAttr{ - Token: syscall.Token(userToken), - - /* TODO: XXX: BUG: HACK: DO NOT SHIP WITH THIS COMMENT: - * These next two lines are commented out, because: - * - We're uncertain of their correctness, especially with regards to integrity level. - * - The permissions are too tight and they interfere with some UI things like notification - * balloon icons. - * These will be reenabled once we've figured out the right way to do it, and this - * program should not ship until we've done so. - - ProcessAttributes: &securityAttributes, - ThreadAttributes: &securityAttributes, - */ + Token: syscall.Token(userToken), + ProcessAttributes: sliceToSecurityAttributes(securityAttributes), + ThreadAttributes: sliceToSecurityAttributes(securityAttributes), }, Files: []*os.File{devNull, devNull, devNull}, Env: env, diff --git a/service/zsyscall_windows.go b/service/zsyscall_windows.go index 6005e2d9..fca55092 100644 --- a/service/zsyscall_windows.go +++ b/service/zsyscall_windows.go @@ -47,6 +47,15 @@ var ( procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory") procGetSecurityInfo = modadvapi32.NewProc("GetSecurityInfo") procGetSecurityDescriptorLength = modadvapi32.NewProc("GetSecurityDescriptorLength") + procAddAccessAllowedAce = modadvapi32.NewProc("AddAccessAllowedAce") + procSetSecurityDescriptorDacl = modadvapi32.NewProc("SetSecurityDescriptorDacl") + procSetSecurityDescriptorSacl = modadvapi32.NewProc("SetSecurityDescriptorSacl") + procGetAclInformation = modadvapi32.NewProc("GetAclInformation") + procGetAce = modadvapi32.NewProc("GetAce") + procAddAce = modadvapi32.NewProc("AddAce") + procInitializeAcl = modadvapi32.NewProc("InitializeAcl") + procMakeAbsoluteSD = modadvapi32.NewProc("MakeAbsoluteSD") + procMakeSelfRelativeSD = modadvapi32.NewProc("MakeSelfRelativeSD") procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock") procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock") procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW") @@ -82,8 +91,8 @@ func wtsFreeMemory(ptr uintptr) { return } -func getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) { - r1, _, e1 := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(sidOwner)), uintptr(unsafe.Pointer(sidGroup)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(securityDescriptor)), 0) +func getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, owner *uintptr, group *uintptr, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) { + r1, _, e1 := syscall.Syscall9(procGetSecurityInfo.Addr(), 8, uintptr(handle), uintptr(objectType), uintptr(si), uintptr(unsafe.Pointer(owner)), uintptr(unsafe.Pointer(group)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), uintptr(unsafe.Pointer(securityDescriptor)), 0) if r1 != 0 { if e1 != 0 { err = errnoErr(e1) @@ -100,6 +109,138 @@ func getSecurityDescriptorLength(securityDescriptor uintptr) (len uint32) { return } +func addAccessAllowedAce(acl uintptr, aceRevision uint32, accessmask uint32, sid *windows.SID) (err error) { + r1, _, e1 := syscall.Syscall6(procAddAccessAllowedAce.Addr(), 4, uintptr(acl), uintptr(aceRevision), uintptr(accessmask), uintptr(unsafe.Pointer(sid)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorDacl(securityDescriptor uintptr, daclPresent bool, dacl uintptr, defaulted bool) (err error) { + var _p0 uint32 + if daclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if defaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorDacl.Addr(), 4, uintptr(securityDescriptor), uintptr(_p0), uintptr(dacl), uintptr(_p1), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func setSecurityDescriptorSacl(securityDescriptor uintptr, saclPresent bool, sacl uintptr, defaulted bool) (err error) { + var _p0 uint32 + if saclPresent { + _p0 = 1 + } else { + _p0 = 0 + } + var _p1 uint32 + if defaulted { + _p1 = 1 + } else { + _p1 = 0 + } + r1, _, e1 := syscall.Syscall6(procSetSecurityDescriptorSacl.Addr(), 4, uintptr(securityDescriptor), uintptr(_p0), uintptr(sacl), uintptr(_p1), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getAclInformation(acl uintptr, info unsafe.Pointer, len uint32, infoclass uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procGetAclInformation.Addr(), 4, uintptr(acl), uintptr(info), uintptr(len), uintptr(infoclass), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func getAce(acl uintptr, index uint32, ace *uintptr) (err error) { + r1, _, e1 := syscall.Syscall(procGetAce.Addr(), 3, uintptr(acl), uintptr(index), uintptr(unsafe.Pointer(ace))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func addAce(acl uintptr, revision uint32, index uint32, ace uintptr, lenAce uint32) (err error) { + r1, _, e1 := syscall.Syscall6(procAddAce.Addr(), 5, uintptr(acl), uintptr(revision), uintptr(index), uintptr(ace), uintptr(lenAce), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func initializeAcl(acl uintptr, len uint32, revision uint32) (err error) { + r1, _, e1 := syscall.Syscall(procInitializeAcl.Addr(), 3, uintptr(acl), uintptr(len), uintptr(revision)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func makeAbsoluteSd(selfRelativeSecurityDescriptor uintptr, absoluteSecurityDescriptor uintptr, absoluteSecurityDescriptorSize *uint32, dacl uintptr, daclSize *uint32, sacl uintptr, saclSize *uint32, owner uintptr, ownerSize *uint32, primaryGroup uintptr, primaryGroupSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall12(procMakeAbsoluteSD.Addr(), 11, uintptr(selfRelativeSecurityDescriptor), uintptr(absoluteSecurityDescriptor), uintptr(unsafe.Pointer(absoluteSecurityDescriptorSize)), uintptr(dacl), uintptr(unsafe.Pointer(daclSize)), uintptr(sacl), uintptr(unsafe.Pointer(saclSize)), uintptr(owner), uintptr(unsafe.Pointer(ownerSize)), uintptr(primaryGroup), uintptr(unsafe.Pointer(primaryGroupSize)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func makeSelfRelativeSd(absoluteSecurityDescriptor uintptr, relativeSecurityDescriptor uintptr, relativeSecurityDescriptorSize *uint32) (err error) { + r1, _, e1 := syscall.Syscall(procMakeSelfRelativeSD.Addr(), 3, uintptr(absoluteSecurityDescriptor), uintptr(relativeSecurityDescriptor), uintptr(unsafe.Pointer(relativeSecurityDescriptorSize))) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + func createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) { var _p0 uint32 if inheritExisting { -- cgit v1.2.3-59-g8ed1b