proc/native: acquire debug programs privilege on Windows (#3162)

On Windows we need to acquire the SeDebugPrivilege privilege to be able
to debug programs owned by different users.
See:

https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/debug-privilege

This procedure will fail if the current user does not have this
privilege so do not complain too much about it.

Fixes #3136
This commit is contained in:
Alessandro Arzilli 2022-10-10 20:01:25 +02:00 committed by GitHub
parent 7d2cf11550
commit beaa04604a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -141,8 +141,20 @@ func findExePath(pid int) (string, error) {
}
}
var debugPrivilegeRequested = false
// Attach to an existing process with the given PID.
func Attach(pid int, _ []string) (*proc.Target, error) {
var aperr error
if !debugPrivilegeRequested {
debugPrivilegeRequested = true
// The following call will only work if the user is an administrator
// has the "Debug Programs" privilege in Local security settings.
// Since this privilege is not needed to debug processes owned by the
// current user, do not complain about this unless attach actually fails.
aperr = acquireDebugPrivilege()
}
dbp := newProcess(pid)
var err error
dbp.execPtraceFunc(func() {
@ -150,6 +162,9 @@ func Attach(pid int, _ []string) (*proc.Target, error) {
err = _DebugActiveProcess(uint32(pid))
})
if err != nil {
if aperr != nil {
return nil, fmt.Errorf("%v also %v", err, aperr)
}
return nil, err
}
exepath, err := findExePath(pid)
@ -164,6 +179,40 @@ func Attach(pid int, _ []string) (*proc.Target, error) {
return tgt, nil
}
// acquireDebugPrivilege acquires the debug privilege which is needed to
// debug other user's processes.
// See:
//
// - https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/debug-privilege
// - https://github.com/go-delve/delve/issues/3136
func acquireDebugPrivilege() error {
var token sys.Token
err := sys.OpenProcessToken(sys.CurrentProcess(), sys.TOKEN_QUERY|sys.TOKEN_ADJUST_PRIVILEGES, &token)
if err != nil {
return fmt.Errorf("could not acquire debug privilege (OpenCurrentProcessToken): %v", err)
}
defer token.Close()
privName, _ := sys.UTF16FromString("SeDebugPrivilege")
var luid sys.LUID
err = sys.LookupPrivilegeValue(nil, &privName[0], &luid)
if err != nil {
return fmt.Errorf("could not acquire debug privilege (LookupPrivilegeValue): %v", err)
}
var tp sys.Tokenprivileges
tp.PrivilegeCount = 1
tp.Privileges[0].Luid = luid
tp.Privileges[0].Attributes = sys.SE_PRIVILEGE_ENABLED
err = sys.AdjustTokenPrivileges(token, false, &tp, 0, nil, nil)
if err != nil {
return fmt.Errorf("could not acquire debug privilege (AdjustTokenPrivileges): %v", err)
}
return nil
}
// kill kills the process.
func (dbp *nativeProcess) kill() error {
if dbp.exited {