From 616a9dc4c0906f42e1b35e94f5e2e200f561f1e9 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Fri, 10 Jan 2003 20:14:02 +0000 Subject: [PATCH] * win32-nat.c (set_process_privilege): New function. (child_attach): Call set_process_privilege() to enable the SE_DEBUG_NAME user privilege if available in process token. --- gdb/ChangeLog | 6 ++++ gdb/win32-nat.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++ gdb/windows-nat.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7ab960e5b1..1bd43a351d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2003-01-07 Corinna Vinschen + + * win32-nat.c (set_process_privilege): New function. + (child_attach): Call set_process_privilege() to enable the + SE_DEBUG_NAME user privilege if available in process token. + 2003-01-10 J. Brobecker * hpread.c (hpread_process_one_debug_symbol): Fix a small diff --git a/gdb/win32-nat.c b/gdb/win32-nat.c index f3fb0a7a97..91d27ae3e7 100644 --- a/gdb/win32-nat.c +++ b/gdb/win32-nat.c @@ -1374,6 +1374,83 @@ has_detach_ability (void) return 0; } +/* Try to set or remove a user privilege to the current process. Return -1 + if that fails, the previous setting of that privilege otherwise. + + This code is copied from the Cygwin source code and rearranged to allow + dynamically loading of the needed symbols from advapi32 which is only + available on NT/2K/XP. */ +static int +set_process_privilege (const char *privilege, BOOL enable) +{ + static HMODULE advapi32 = NULL; + static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE); + static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID); + static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, + DWORD, PTOKEN_PRIVILEGES, PDWORD); + + HANDLE token_hdl = NULL; + LUID restore_priv; + TOKEN_PRIVILEGES new_priv, orig_priv; + int ret = -1; + DWORD size; + + if (GetVersion () >= 0x80000000) /* No security availbale on 9x/Me */ + return 0; + + if (!advapi32) + { + if (!(advapi32 = LoadLibrary ("advapi32.dll"))) + goto out; + if (!OpenProcessToken) + OpenProcessToken = GetProcAddress (advapi32, "OpenProcessToken"); + if (!LookupPrivilegeValue) + LookupPrivilegeValue = GetProcAddress (advapi32, + "LookupPrivilegeValueA"); + if (!AdjustTokenPrivileges) + AdjustTokenPrivileges = GetProcAddress (advapi32, + "AdjustTokenPrivileges"); + if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges) + { + advapi32 = NULL; + goto out; + } + } + + if (!OpenProcessToken (GetCurrentProcess (), + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, + &token_hdl)) + goto out; + + if (!LookupPrivilegeValue (NULL, privilege, &restore_priv)) + goto out; + + new_priv.PrivilegeCount = 1; + new_priv.Privileges[0].Luid = restore_priv; + new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; + + if (!AdjustTokenPrivileges (token_hdl, FALSE, &new_priv, + sizeof orig_priv, &orig_priv, &size)) + goto out; +#if 0 + /* Disabled, otherwise every `attach' in an unprivileged user session + would raise the "Failed to get SE_DEBUG_NAME privilege" warning in + child_attach(). */ + /* AdjustTokenPrivileges returns TRUE even if the privilege could not + be enabled. GetLastError () returns an correct error code, though. */ + if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED) + goto out; +#endif + + ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0; + +out: + if (token_hdl) + CloseHandle (token_hdl); + + return ret; +} + /* Attach to process PID, then initialize for debugging it. */ static void child_attach (char *args, int from_tty) @@ -1384,6 +1461,12 @@ child_attach (char *args, int from_tty) if (!args) error_no_arg ("process-id to attach"); + if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0) + { + printf_unfiltered ("Warning: Failed to get SE_DEBUG_NAME privilege\n"); + printf_unfiltered ("This can cause attach to fail on Windows NT/2K/XP\n"); + } + pid = strtoul (args, 0, 0); ok = DebugActiveProcess (pid); saw_create = 0; diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c index f3fb0a7a97..91d27ae3e7 100644 --- a/gdb/windows-nat.c +++ b/gdb/windows-nat.c @@ -1374,6 +1374,83 @@ has_detach_ability (void) return 0; } +/* Try to set or remove a user privilege to the current process. Return -1 + if that fails, the previous setting of that privilege otherwise. + + This code is copied from the Cygwin source code and rearranged to allow + dynamically loading of the needed symbols from advapi32 which is only + available on NT/2K/XP. */ +static int +set_process_privilege (const char *privilege, BOOL enable) +{ + static HMODULE advapi32 = NULL; + static BOOL WINAPI (*OpenProcessToken)(HANDLE, DWORD, PHANDLE); + static BOOL WINAPI (*LookupPrivilegeValue)(LPCSTR, LPCSTR, PLUID); + static BOOL WINAPI (*AdjustTokenPrivileges)(HANDLE, BOOL, PTOKEN_PRIVILEGES, + DWORD, PTOKEN_PRIVILEGES, PDWORD); + + HANDLE token_hdl = NULL; + LUID restore_priv; + TOKEN_PRIVILEGES new_priv, orig_priv; + int ret = -1; + DWORD size; + + if (GetVersion () >= 0x80000000) /* No security availbale on 9x/Me */ + return 0; + + if (!advapi32) + { + if (!(advapi32 = LoadLibrary ("advapi32.dll"))) + goto out; + if (!OpenProcessToken) + OpenProcessToken = GetProcAddress (advapi32, "OpenProcessToken"); + if (!LookupPrivilegeValue) + LookupPrivilegeValue = GetProcAddress (advapi32, + "LookupPrivilegeValueA"); + if (!AdjustTokenPrivileges) + AdjustTokenPrivileges = GetProcAddress (advapi32, + "AdjustTokenPrivileges"); + if (!OpenProcessToken || !LookupPrivilegeValue || !AdjustTokenPrivileges) + { + advapi32 = NULL; + goto out; + } + } + + if (!OpenProcessToken (GetCurrentProcess (), + TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, + &token_hdl)) + goto out; + + if (!LookupPrivilegeValue (NULL, privilege, &restore_priv)) + goto out; + + new_priv.PrivilegeCount = 1; + new_priv.Privileges[0].Luid = restore_priv; + new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; + + if (!AdjustTokenPrivileges (token_hdl, FALSE, &new_priv, + sizeof orig_priv, &orig_priv, &size)) + goto out; +#if 0 + /* Disabled, otherwise every `attach' in an unprivileged user session + would raise the "Failed to get SE_DEBUG_NAME privilege" warning in + child_attach(). */ + /* AdjustTokenPrivileges returns TRUE even if the privilege could not + be enabled. GetLastError () returns an correct error code, though. */ + if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED) + goto out; +#endif + + ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0; + +out: + if (token_hdl) + CloseHandle (token_hdl); + + return ret; +} + /* Attach to process PID, then initialize for debugging it. */ static void child_attach (char *args, int from_tty) @@ -1384,6 +1461,12 @@ child_attach (char *args, int from_tty) if (!args) error_no_arg ("process-id to attach"); + if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0) + { + printf_unfiltered ("Warning: Failed to get SE_DEBUG_NAME privilege\n"); + printf_unfiltered ("This can cause attach to fail on Windows NT/2K/XP\n"); + } + pid = strtoul (args, 0, 0); ok = DebugActiveProcess (pid); saw_create = 0;