* cygheap.cc (cygheap_init): Accomodate set_process_privilege change.
* cygheap.h (cygheap_user::curr_primary_token): New member. (cygheap_user::primary_token): New method. (cygheap_user::deimpersonate): Always revert to processes' impersonation token. (cygheap_user::reimpersonate): Set processes' or setuid token as necessary. (cygheap_user::has_impersonation_tokens): Look for curr_primary_token value. (cygheap_user::close_impersonation_tokens): Close curr_primary_token here if necessary. Don't reset token values to NO_IMPERSONATION since that's done in uinfo_init anyway. (init_cygheap::luid): New LUID array keeping privilege LUIDs. * cygtls.cc (_cygtls::init_thread): Call cygheap->user.reimpersonate. * dcrt0.cc (hProcToken): New global variable to keep process token. (hProcImpToken): Ditto for process impersonation token. (dll_crt0_0): Open process token here once. Duplicate to create hProcImpToken. (dll_crt0_1): Call set_cygwin_privileges. * environ.cc (allow_ntea): Drop duplicate declaration. (allow_smbntsec): Ditto. (set_traverse): Only set allow_traverse here. (environ_init): Ditto. * fhandler_disk_file.cc (fhandler_disk_file::fchmod): Drop call to enable_restore_privilege. (fhandler_disk_file::fchown): Ditto. (fhandler_disk_file::facl): Ditto. * fork.cc (fork_child): Move call to cygheap->user.reimpersonate after syn with parent. Call set_cygwin_privileges. * grp.cc (internal_getgroups): Use hProcImpToken instead of opening process token. * path.cc (fs_info::update): Bypass traverse checking when retrieving volume information using push/pop_thread_privileges. * registry.cc (load_registry_hive): Drop setting restore privilege since it's already set if available. * sec_helper.cc: Include cygtls.h. (cygpriv): Privilege string array. (privilege_luid): New function, evaluate LUID from cygpriv_idx. (privilege_luid_by_name): New function, evaluate LUID from privilege string. (privilege_name): New function, evaluate privilege string from cygpriv_idx. (set_privilege): New static function called by set_process_privilege and set_thread_privilege. Call privilege_luid to get privilege LUID. Fix bug in return value evaluation. Improve debug output. (set_cygwin_privileges): New function. (set_process_privilege): Remove. (enable_restore_privilege): Remove. * security.cc (allow_traverse): New global variable. (sys_privs): Change type to cygpriv_idx and store privilege indices instead of strings. (SYSTEM_PRIVILEGES_COUNT): Renamed from SYSTEM_PERMISSION_COUNT. (get_system_priv_list): Don't use numerical constant in malloc call. Use privilege_luid to get privilege LUIDs. (get_priv_list): Call privilege_luid_by_name to get LUIDs. Improve inner privilege LUID comparison loop. (create_token): Enable create token privilege using push/pop_self_privileges. Use hProcToken instead of opening process token. Use default DACL when duplicating token. (subauth): Enable tcb privilege using push/pop_self_privileges. Use sec_none instead of homw made security attributes when duplicating token. (check_file_access): Don't duplicate access token, use active impersonation token as is. * security.h (enum cygpriv_idx): New enumeration type enumerating possible privileges. (privilege_luid): Declare new function. (privilege_luid_by_name): Ditto. (privilege_name): Ditto. (allow_traverse): Declare. (set_privilege): Declare function. (set_process_privilege): Define as macro. (enable_restore_privilege): Remove declaration. (_push_thread_privilege): Define macro. (push_thread_privilege): Ditto. (pop_thread_privilege): Ditto. (pop_self_privilege): Ditto. * spawn.cc (spawn_guts): Use cygheap->user.primary_token instead of cygheap->user.token. * syscalls.cc (statvfs): Bypass traverse checking when retrieving volume information using push/pop_thread_privileges. Rearrange code to simplify push/pop bracketing. (seteuid32): Use hProcToken instead of opening process token. Call cygheap->user.deimpersonate instead of RevertToSelf. Create impersonation token from primary internal or external token. Set cygheap->user.curr_primary_token and cygheap->user.current_token privileges once here. Drop "failed" and "failed_ptok" labels. Drop setting DefaultDacl of process token. (setegid32): Use hProcToken and hProcImpToken instead of opening process token. Always reimpersonate afterwards. * uinfo.cc (cygheap_user::init): Use hProcToken instead of opening process token. (internal_getlogin): Ditto. Set hProcImpToken, too. (uinfo_init): Initialize cygheap->user.curr_primary_token. * winsup.h (hProcToken): Declare. (hProcImpToken): Declare.
This commit is contained in:
@@ -30,6 +30,7 @@ details. */
|
||||
#include "dtable.h"
|
||||
#include "pinfo.h"
|
||||
#include "cygheap.h"
|
||||
#include "cygtls.h"
|
||||
#include "pwdgrp.h"
|
||||
|
||||
/* General purpose security attribute objects for global use. */
|
||||
@@ -321,37 +322,95 @@ got_it:
|
||||
#undef DOMLEN
|
||||
#endif //unused
|
||||
|
||||
int
|
||||
set_process_privilege (const char *privilege, bool enable, bool use_thread)
|
||||
/* Order must be same as cygperm_idx in winsup.h. */
|
||||
static const char *cygpriv[] =
|
||||
{
|
||||
HANDLE hToken = NULL;
|
||||
LUID priv_luid;
|
||||
TOKEN_PRIVILEGES new_priv, orig_priv;
|
||||
int ret = -1;
|
||||
DWORD size;
|
||||
SE_CREATE_TOKEN_NAME,
|
||||
SE_ASSIGNPRIMARYTOKEN_NAME,
|
||||
SE_LOCK_MEMORY_NAME,
|
||||
SE_INCREASE_QUOTA_NAME,
|
||||
SE_UNSOLICITED_INPUT_NAME,
|
||||
SE_MACHINE_ACCOUNT_NAME,
|
||||
SE_TCB_NAME,
|
||||
SE_SECURITY_NAME,
|
||||
SE_TAKE_OWNERSHIP_NAME,
|
||||
SE_LOAD_DRIVER_NAME,
|
||||
SE_SYSTEM_PROFILE_NAME,
|
||||
SE_SYSTEMTIME_NAME,
|
||||
SE_PROF_SINGLE_PROCESS_NAME,
|
||||
SE_INC_BASE_PRIORITY_NAME,
|
||||
SE_CREATE_PAGEFILE_NAME,
|
||||
SE_CREATE_PERMANENT_NAME,
|
||||
SE_BACKUP_NAME,
|
||||
SE_RESTORE_NAME,
|
||||
SE_SHUTDOWN_NAME,
|
||||
SE_DEBUG_NAME,
|
||||
SE_AUDIT_NAME,
|
||||
SE_SYSTEM_ENVIRONMENT_NAME,
|
||||
SE_CHANGE_NOTIFY_NAME,
|
||||
SE_REMOTE_SHUTDOWN_NAME,
|
||||
SE_CREATE_GLOBAL_NAME,
|
||||
SE_UNDOCK_NAME,
|
||||
SE_MANAGE_VOLUME_NAME,
|
||||
SE_IMPERSONATE_NAME,
|
||||
SE_ENABLE_DELEGATION_NAME,
|
||||
SE_SYNC_AGENT_NAME
|
||||
};
|
||||
|
||||
if (!LookupPrivilegeValue (NULL, privilege, &priv_luid))
|
||||
const LUID *
|
||||
privilege_luid (cygpriv_idx idx)
|
||||
{
|
||||
if (idx < 0 || idx >= SE_NUM_PRIVS)
|
||||
return NULL;
|
||||
if (!cygheap->luid[idx].LowPart && !cygheap->luid[idx].HighPart
|
||||
&& !LookupPrivilegeValue (NULL, cygpriv[idx], &cygheap->luid[idx]))
|
||||
{
|
||||
__seterrno ();
|
||||
goto out;
|
||||
return NULL;
|
||||
}
|
||||
return &cygheap->luid[idx];
|
||||
}
|
||||
|
||||
if ((use_thread
|
||||
&& !OpenThreadToken (GetCurrentThread (), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
||||
0, &hToken))
|
||||
||(!use_thread
|
||||
&& !OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES,
|
||||
&hToken)))
|
||||
const LUID *
|
||||
privilege_luid_by_name (const char *pname)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (!pname)
|
||||
return NULL;
|
||||
for (idx = 0; idx < SE_NUM_PRIVS; ++idx)
|
||||
if (!strcmp (pname, cygpriv[idx]))
|
||||
return privilege_luid ((cygpriv_idx) idx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
privilege_name (cygpriv_idx idx)
|
||||
{
|
||||
if (idx < 0 || idx >= SE_NUM_PRIVS)
|
||||
return "<unknown privilege>";
|
||||
return cygpriv[idx];
|
||||
}
|
||||
|
||||
int
|
||||
set_privilege (HANDLE token, cygpriv_idx privilege, bool enable)
|
||||
{
|
||||
int ret = -1;
|
||||
const LUID *priv_luid;
|
||||
TOKEN_PRIVILEGES new_priv, orig_priv;
|
||||
DWORD size;
|
||||
|
||||
if (!(priv_luid = privilege_luid (privilege)))
|
||||
{
|
||||
__seterrno ();
|
||||
goto out;
|
||||
}
|
||||
|
||||
new_priv.PrivilegeCount = 1;
|
||||
new_priv.Privileges[0].Luid = priv_luid;
|
||||
new_priv.Privileges[0].Luid = *priv_luid;
|
||||
new_priv.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0;
|
||||
|
||||
if (!AdjustTokenPrivileges (hToken, FALSE, &new_priv,
|
||||
if (!AdjustTokenPrivileges (token, FALSE, &new_priv,
|
||||
sizeof orig_priv, &orig_priv, &size))
|
||||
{
|
||||
__seterrno ();
|
||||
@@ -365,28 +424,23 @@ set_process_privilege (const char *privilege, bool enable, bool use_thread)
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = orig_priv.Privileges[0].Attributes == SE_PRIVILEGE_ENABLED ? 1 : 0;
|
||||
/* If orig_priv.PrivilegeCount is 0, the privilege hasn't been changed. */
|
||||
if (!orig_priv.PrivilegeCount)
|
||||
ret = enable ? 1 : 0;
|
||||
else
|
||||
ret = (orig_priv.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED) ? 1 : 0;
|
||||
|
||||
out:
|
||||
if (hToken)
|
||||
CloseHandle (hToken);
|
||||
|
||||
syscall_printf ("%d = set_process_privilege (%s, %d)", ret, privilege, enable);
|
||||
syscall_printf ("%d = set_privilege ((token %x) %s, %d)",
|
||||
ret, token, privilege_name (privilege), enable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Helper function to set the SE_RESTORE_NAME privilege once. */
|
||||
void
|
||||
enable_restore_privilege ()
|
||||
set_cygwin_privileges (HANDLE token)
|
||||
{
|
||||
static int NO_COPY saved_res;
|
||||
bool issetuid = cygheap->user.issetuid ();
|
||||
if (!saved_res || issetuid)
|
||||
{
|
||||
int res = 2 + set_process_privilege (SE_RESTORE_NAME, true, issetuid);
|
||||
if (!issetuid)
|
||||
saved_res = res;
|
||||
}
|
||||
set_privilege (token, SE_RESTORE_PRIV, true);
|
||||
set_privilege (token, SE_CHANGE_NOTIFY_PRIV, !allow_traverse);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user