mirror of
https://github.com/tailscale/tailscale.git
synced 2025-07-30 15:53:45 +00:00
util/winutil: simplify dropping privileges after use (#10099)
To safely request and drop privileges, runtime.Lock/UnlockOSThread and windows.Impersonate/RevertToSelf should be called. Add these calls to winutil.EnableCurrentThreadPrivilege so that callers don't need to worry about it. Updates https://github.com/tailscale/corp/issues/15488 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
parent
ef6a6e94f1
commit
aba4bd0c62
@ -225,14 +225,32 @@ func isSIDValidPrincipal(uid string) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableCurrentThreadPrivilege enables the named privilege
|
// EnableCurrentThreadPrivilege enables the named privilege in the current
|
||||||
// in the current thread access token.
|
// thread access token. The current goroutine is also locked to the OS thread
|
||||||
func EnableCurrentThreadPrivilege(name string) error {
|
// (runtime.LockOSThread). Callers must call the returned disable function when
|
||||||
|
// done with the privileged task.
|
||||||
|
func EnableCurrentThreadPrivilege(name string) (disable func() error, err error) {
|
||||||
|
runtime.LockOSThread()
|
||||||
|
|
||||||
|
if err := windows.ImpersonateSelf(windows.SecurityImpersonation); err != nil {
|
||||||
|
runtime.UnlockOSThread()
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
disable = func() error {
|
||||||
|
defer runtime.UnlockOSThread()
|
||||||
|
return windows.RevertToSelf()
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
disable()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
var t windows.Token
|
var t windows.Token
|
||||||
err := windows.OpenThreadToken(windows.CurrentThread(),
|
err = windows.OpenThreadToken(windows.CurrentThread(),
|
||||||
windows.TOKEN_QUERY|windows.TOKEN_ADJUST_PRIVILEGES, false, &t)
|
windows.TOKEN_QUERY|windows.TOKEN_ADJUST_PRIVILEGES, false, &t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer t.Close()
|
defer t.Close()
|
||||||
|
|
||||||
@ -240,15 +258,15 @@ func EnableCurrentThreadPrivilege(name string) error {
|
|||||||
|
|
||||||
privStr, err := syscall.UTF16PtrFromString(name)
|
privStr, err := syscall.UTF16PtrFromString(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = windows.LookupPrivilegeValue(nil, privStr, &tp.Privileges[0].Luid)
|
err = windows.LookupPrivilegeValue(nil, privStr, &tp.Privileges[0].Luid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
tp.PrivilegeCount = 1
|
tp.PrivilegeCount = 1
|
||||||
tp.Privileges[0].Attributes = windows.SE_PRIVILEGE_ENABLED
|
tp.Privileges[0].Attributes = windows.SE_PRIVILEGE_ENABLED
|
||||||
return windows.AdjustTokenPrivileges(t, false, &tp, 0, nil, nil)
|
return disable, windows.AdjustTokenPrivileges(t, false, &tp, 0, nil, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartProcessAsChild starts exePath process as a child of parentPID.
|
// StartProcessAsChild starts exePath process as a child of parentPID.
|
||||||
@ -256,16 +274,7 @@ func EnableCurrentThreadPrivilege(name string) error {
|
|||||||
// the new process, along with any optional environment variables in extraEnv.
|
// the new process, along with any optional environment variables in extraEnv.
|
||||||
func StartProcessAsChild(parentPID uint32, exePath string, extraEnv []string) error {
|
func StartProcessAsChild(parentPID uint32, exePath string, extraEnv []string) error {
|
||||||
// The rest of this function requires SeDebugPrivilege to be held.
|
// The rest of this function requires SeDebugPrivilege to be held.
|
||||||
|
//
|
||||||
runtime.LockOSThread()
|
|
||||||
defer runtime.UnlockOSThread()
|
|
||||||
|
|
||||||
err := windows.ImpersonateSelf(windows.SecurityImpersonation)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer windows.RevertToSelf()
|
|
||||||
|
|
||||||
// According to https://docs.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
|
// According to https://docs.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
|
||||||
//
|
//
|
||||||
// ... To open a handle to another process and obtain full access rights,
|
// ... To open a handle to another process and obtain full access rights,
|
||||||
@ -277,10 +286,11 @@ func StartProcessAsChild(parentPID uint32, exePath string, extraEnv []string) er
|
|||||||
//
|
//
|
||||||
// TODO: try look for something less than SeDebugPrivilege
|
// TODO: try look for something less than SeDebugPrivilege
|
||||||
|
|
||||||
err = EnableCurrentThreadPrivilege("SeDebugPrivilege")
|
disableSeDebug, err := EnableCurrentThreadPrivilege("SeDebugPrivilege")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer disableSeDebug()
|
||||||
|
|
||||||
ph, err := windows.OpenProcess(
|
ph, err := windows.OpenProcess(
|
||||||
windows.PROCESS_CREATE_PROCESS|windows.PROCESS_QUERY_INFORMATION|windows.PROCESS_DUP_HANDLE,
|
windows.PROCESS_CREATE_PROCESS|windows.PROCESS_QUERY_INFORMATION|windows.PROCESS_DUP_HANDLE,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user