* 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:
@@ -1698,6 +1698,7 @@ get_osfhandle (int fd)
|
||||
extern "C" int
|
||||
statvfs (const char *fname, struct statvfs *sfs)
|
||||
{
|
||||
int ret = -1;
|
||||
char root[CYG_MAX_PATH];
|
||||
|
||||
if (check_null_empty_str_errno (fname)
|
||||
@@ -1716,47 +1717,47 @@ statvfs (const char *fname, struct statvfs *sfs)
|
||||
if (!rootdir (full_path, root))
|
||||
return -1;
|
||||
|
||||
ULARGE_INTEGER availb, freeb, totalb;
|
||||
DWORD spc, bps, availc, freec, totalc, vsn, maxlen, flags;
|
||||
BOOL status;
|
||||
|
||||
push_thread_privilege (SE_CHANGE_NOTIFY_PRIV, true);
|
||||
|
||||
/* GetDiskFreeSpaceEx must be called before GetDiskFreeSpace on
|
||||
WinME, to avoid the MS KB 314417 bug */
|
||||
ULARGE_INTEGER availb, freeb, totalb;
|
||||
BOOL status = GetDiskFreeSpaceEx (root, &availb, &totalb, &freeb);
|
||||
|
||||
DWORD spc, bps, availc, freec, totalc;
|
||||
|
||||
if (!GetDiskFreeSpace (root, &spc, &bps, &freec, &totalc))
|
||||
status = GetDiskFreeSpaceEx (root, &availb, &totalb, &freeb);
|
||||
if (GetDiskFreeSpace (root, &spc, &bps, &freec, &totalc))
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
if (status)
|
||||
{
|
||||
availc = availb.QuadPart / (spc*bps);
|
||||
totalc = totalb.QuadPart / (spc*bps);
|
||||
freec = freeb.QuadPart / (spc*bps);
|
||||
}
|
||||
else
|
||||
availc = freec;
|
||||
if (GetVolumeInformation (root, NULL, 0, &vsn, &maxlen, &flags, NULL, 0))
|
||||
{
|
||||
sfs->f_bsize = spc*bps;
|
||||
sfs->f_frsize = spc*bps;
|
||||
sfs->f_blocks = totalc;
|
||||
sfs->f_bfree = freec;
|
||||
sfs->f_bavail = availc;
|
||||
sfs->f_files = ULONG_MAX;
|
||||
sfs->f_ffree = ULONG_MAX;
|
||||
sfs->f_favail = ULONG_MAX;
|
||||
sfs->f_fsid = vsn;
|
||||
sfs->f_flag = flags;
|
||||
sfs->f_namemax = maxlen;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
__seterrno ();
|
||||
|
||||
if (status)
|
||||
{
|
||||
availc = availb.QuadPart / (spc*bps);
|
||||
totalc = totalb.QuadPart / (spc*bps);
|
||||
freec = freeb.QuadPart / (spc*bps);
|
||||
}
|
||||
else
|
||||
availc = freec;
|
||||
pop_thread_privilege ();
|
||||
|
||||
DWORD vsn, maxlen, flags;
|
||||
|
||||
if (!GetVolumeInformation (root, NULL, 0, &vsn, &maxlen, &flags, NULL, 0))
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
sfs->f_bsize = spc*bps;
|
||||
sfs->f_frsize = spc*bps;
|
||||
sfs->f_blocks = totalc;
|
||||
sfs->f_bfree = freec;
|
||||
sfs->f_bavail = availc;
|
||||
sfs->f_files = ULONG_MAX;
|
||||
sfs->f_ffree = ULONG_MAX;
|
||||
sfs->f_favail = ULONG_MAX;
|
||||
sfs->f_fsid = vsn;
|
||||
sfs->f_flag = flags;
|
||||
sfs->f_namemax = maxlen;
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
@@ -1968,11 +1969,9 @@ seteuid32 (__uid32_t uid)
|
||||
|
||||
cygsid usersid;
|
||||
user_groups &groups = cygheap->user.groups;
|
||||
HANDLE ptok, new_token = INVALID_HANDLE_VALUE;
|
||||
HANDLE new_token = INVALID_HANDLE_VALUE;
|
||||
struct passwd * pw_new;
|
||||
bool token_is_internal, issamesid = false;
|
||||
char dacl_buf[MAX_DACL_LEN (5)];
|
||||
TOKEN_DEFAULT_DACL tdacl = {};
|
||||
|
||||
pw_new = internal_getpwuid (uid);
|
||||
if (!wincap.has_security () && pw_new)
|
||||
@@ -1986,29 +1985,24 @@ seteuid32 (__uid32_t uid)
|
||||
return -1;
|
||||
}
|
||||
|
||||
RevertToSelf ();
|
||||
if (!OpenProcessToken (hMainProc, TOKEN_QUERY | TOKEN_ADJUST_DEFAULT, &ptok))
|
||||
{
|
||||
__seterrno ();
|
||||
goto failed_ptok;;
|
||||
}
|
||||
cygheap->user.deimpersonate ();
|
||||
|
||||
/* Verify if the process token is suitable. */
|
||||
if (verify_token (ptok, usersid, groups))
|
||||
new_token = ptok;
|
||||
if (verify_token (hProcToken, usersid, groups))
|
||||
new_token = hProcToken;
|
||||
/* Verify if the external token is suitable */
|
||||
else if (cygheap->user.external_token != NO_IMPERSONATION
|
||||
&& verify_token (cygheap->user.external_token, usersid, groups))
|
||||
new_token = cygheap->user.external_token;
|
||||
/* Verify if the current token (internal or former external) is suitable */
|
||||
else if (cygheap->user.current_token != NO_IMPERSONATION
|
||||
&& cygheap->user.current_token != cygheap->user.external_token
|
||||
&& verify_token (cygheap->user.current_token, usersid, groups,
|
||||
else if (cygheap->user.curr_primary_token != NO_IMPERSONATION
|
||||
&& cygheap->user.curr_primary_token != cygheap->user.external_token
|
||||
&& verify_token (cygheap->user.curr_primary_token, usersid, groups,
|
||||
&token_is_internal))
|
||||
new_token = cygheap->user.current_token;
|
||||
new_token = cygheap->user.curr_primary_token;
|
||||
/* Verify if the internal token is suitable */
|
||||
else if (cygheap->user.internal_token != NO_IMPERSONATION
|
||||
&& cygheap->user.internal_token != cygheap->user.current_token
|
||||
&& cygheap->user.internal_token != cygheap->user.curr_primary_token
|
||||
&& verify_token (cygheap->user.internal_token, usersid, groups,
|
||||
&token_is_internal))
|
||||
new_token = cygheap->user.internal_token;
|
||||
@@ -2026,7 +2020,10 @@ seteuid32 (__uid32_t uid)
|
||||
debug_printf ("create token failed, try subauthentication.");
|
||||
new_token = subauth (pw_new);
|
||||
if (new_token == INVALID_HANDLE_VALUE)
|
||||
goto failed;
|
||||
{
|
||||
cygheap->user.reimpersonate ();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* Keep at most one internal token */
|
||||
if (cygheap->user.internal_token != NO_IMPERSONATION)
|
||||
@@ -2034,17 +2031,7 @@ seteuid32 (__uid32_t uid)
|
||||
cygheap->user.internal_token = new_token;
|
||||
}
|
||||
|
||||
/* Set process def dacl to allow access to impersonated token */
|
||||
if (sec_acl ((PACL) dacl_buf, true, true, usersid))
|
||||
{
|
||||
tdacl.DefaultDacl = (PACL) dacl_buf;
|
||||
if (!SetTokenInformation (ptok, TokenDefaultDacl,
|
||||
&tdacl, sizeof dacl_buf))
|
||||
debug_printf ("SetTokenInformation"
|
||||
"(TokenDefaultDacl), %E");
|
||||
}
|
||||
|
||||
if (new_token != ptok)
|
||||
if (new_token != hProcToken)
|
||||
{
|
||||
/* Avoid having HKCU use default user */
|
||||
char name[128];
|
||||
@@ -2053,26 +2040,48 @@ seteuid32 (__uid32_t uid)
|
||||
/* Try setting owner to same value as user. */
|
||||
if (!SetTokenInformation (new_token, TokenOwner,
|
||||
&usersid, sizeof usersid))
|
||||
debug_printf ("SetTokenInformation(user.token, "
|
||||
"TokenOwner), %E");
|
||||
debug_printf ("SetTokenInformation(user.token, TokenOwner), %E");
|
||||
/* Try setting primary group in token to current group */
|
||||
if (!SetTokenInformation (new_token, TokenPrimaryGroup,
|
||||
&groups.pgsid, sizeof (cygsid)))
|
||||
debug_printf ("SetTokenInformation(user.token, "
|
||||
"TokenPrimaryGroup), %E");
|
||||
debug_printf ("SetTokenInformation(user.token, TokenPrimaryGroup), %E");
|
||||
/* Try setting default DACL */
|
||||
if (tdacl.DefaultDacl
|
||||
&& !SetTokenInformation (new_token, TokenDefaultDacl,
|
||||
&tdacl, sizeof (tdacl)))
|
||||
debug_printf ("SetTokenInformation (TokenDefaultDacl), %E");
|
||||
char dacl_buf[MAX_DACL_LEN (5)];
|
||||
if (sec_acl ((PACL) dacl_buf, true, true, usersid))
|
||||
{
|
||||
TOKEN_DEFAULT_DACL tdacl = { (PACL) dacl_buf };
|
||||
if (!SetTokenInformation (new_token, TokenDefaultDacl,
|
||||
&tdacl, sizeof (tdacl)))
|
||||
debug_printf ("SetTokenInformation (TokenDefaultDacl), %E");
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle (ptok);
|
||||
issamesid = (usersid == cygheap->user.sid ());
|
||||
cygheap->user.set_sid (usersid);
|
||||
cygheap->user.current_token = new_token == ptok ? NO_IMPERSONATION
|
||||
: new_token;
|
||||
cygheap->user.reimpersonate ();
|
||||
cygheap->user.curr_primary_token = new_token == hProcToken ? NO_IMPERSONATION
|
||||
: new_token;
|
||||
if (cygheap->user.current_token != NO_IMPERSONATION)
|
||||
{
|
||||
CloseHandle (cygheap->user.current_token);
|
||||
cygheap->user.current_token = NO_IMPERSONATION;
|
||||
}
|
||||
if (cygheap->user.curr_primary_token != NO_IMPERSONATION)
|
||||
{
|
||||
if (!DuplicateTokenEx (cygheap->user.curr_primary_token, MAXIMUM_ALLOWED,
|
||||
&sec_none, SecurityImpersonation,
|
||||
TokenImpersonation, &cygheap->user.current_token))
|
||||
{
|
||||
__seterrno ();
|
||||
cygheap->user.curr_primary_token = NO_IMPERSONATION;
|
||||
return -1;
|
||||
}
|
||||
set_cygwin_privileges (cygheap->user.current_token);
|
||||
}
|
||||
if (!cygheap->user.reimpersonate ())
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
success_9x:
|
||||
cygheap->user.set_name (pw_new->pw_name);
|
||||
@@ -2081,12 +2090,6 @@ success_9x:
|
||||
if (!issamesid)
|
||||
user_shared_initialize (true);
|
||||
return 0;
|
||||
|
||||
failed:
|
||||
CloseHandle (ptok);
|
||||
failed_ptok:
|
||||
cygheap->user.reimpersonate ();
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int
|
||||
@@ -2151,7 +2154,6 @@ setegid32 (__gid32_t gid)
|
||||
|
||||
user_groups * groups = &cygheap->user.groups;
|
||||
cygsid gsid;
|
||||
HANDLE ptok;
|
||||
struct __group32 * gr = internal_getgrgid (gid);
|
||||
|
||||
if (!gsid.getfromgr (gr))
|
||||
@@ -2162,29 +2164,24 @@ setegid32 (__gid32_t gid)
|
||||
myself->gid = gid;
|
||||
|
||||
groups->update_pgrp (gsid);
|
||||
/* If impersonated, update primary group and revert */
|
||||
if (cygheap->user.issetuid ())
|
||||
{
|
||||
if (!SetTokenInformation (cygheap->user.token (),
|
||||
TokenPrimaryGroup,
|
||||
&gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(thread, "
|
||||
/* If impersonated, update impersonation token... */
|
||||
if (!SetTokenInformation (cygheap->user.primary_token (),
|
||||
TokenPrimaryGroup, &gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(primary_token, "
|
||||
"TokenPrimaryGroup), %E");
|
||||
RevertToSelf ();
|
||||
}
|
||||
if (!OpenProcessToken (hMainProc, TOKEN_ADJUST_DEFAULT, &ptok))
|
||||
debug_printf ("OpenProcessToken(), %E");
|
||||
else
|
||||
{
|
||||
if (!SetTokenInformation (ptok, TokenPrimaryGroup,
|
||||
if (!SetTokenInformation (cygheap->user.token (), TokenPrimaryGroup,
|
||||
&gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(process, "
|
||||
"TokenPrimaryGroup), %E");
|
||||
CloseHandle (ptok);
|
||||
debug_printf ("SetTokenInformation(token, TokenPrimaryGroup), %E");
|
||||
}
|
||||
if (cygheap->user.issetuid ()
|
||||
&& !ImpersonateLoggedOnUser (cygheap->user.token ()))
|
||||
system_printf ("Impersonating in setegid failed, %E");
|
||||
cygheap->user.deimpersonate ();
|
||||
if (!SetTokenInformation (hProcToken, TokenPrimaryGroup, &gsid, sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(hProcToken, TokenPrimaryGroup), %E");
|
||||
if (!SetTokenInformation (hProcImpToken, TokenPrimaryGroup, &gsid,
|
||||
sizeof gsid))
|
||||
debug_printf ("SetTokenInformation(hProcImpToken, TokenPrimaryGroup), %E");
|
||||
cygheap->user.reimpersonate ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user