Fix various OS-related comments

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2015-12-15 21:43:33 +01:00
parent bb0fc7a2c0
commit 00e9bf2bb3
12 changed files with 68 additions and 93 deletions

View File

@ -207,17 +207,16 @@ enum fcwd_version_t {
FCWD_W8 FCWD_W8
}; };
/* This class is used to store the CWD starting with Windows Vista. /* This class is used to store the CWD. The CWD storage in the
The CWD storage in the RTL_USER_PROCESS_PARAMETERS block is only RTL_USER_PROCESS_PARAMETERS block is only an afterthought now. The actual
an afterthought now. The actual CWD storage is a FAST_CWD structure CWD storage is a FAST_CWD structure which is allocated on the process heap.
which is allocated on the process heap. The new method only requires The new method only requires minimal locking and it's much more multi-thread
minimal locking and it's much more multi-thread friendly. Presumably friendly. Presumably it minimizes contention when accessing the CWD.
it minimizes contention when accessing the CWD.
The class fcwd_access_t is supposed to encapsulate the gory implementation The class fcwd_access_t is supposed to encapsulate the gory implementation
details depending on OS version from the calling functions. details depending on OS version from the calling functions.
The layout of all structures has been tested on 32 and 64 bit. */ The layout of all structures has been tested on 32 and 64 bit. */
class fcwd_access_t { class fcwd_access_t {
/* This is the layout used in Windows 8. */ /* This is the layout used in Windows 8 and later. */
struct FAST_CWD_8 { struct FAST_CWD_8 {
LONG ReferenceCount; /* Only release when this is 0. */ LONG ReferenceCount; /* Only release when this is 0. */
HANDLE DirectoryHandle; HANDLE DirectoryHandle;

View File

@ -523,13 +523,12 @@ void dll_list::load_after_fork_impl (HANDLE parent, dll* d, int retries)
We DONT_RESOLVE_DLL_REFERENCES at first in case the DLL lands in We DONT_RESOLVE_DLL_REFERENCES at first in case the DLL lands in
the wrong spot; the wrong spot;
NOTE: This step skips DLLs which loaded at their preferred NOTE: This step skips DLLs which loaded at their preferred address in
address in the parent because they should behave (we already the parent because they should behave (we already verified that their
verified that their preferred address in the child is preferred address in the child is available). However, this may fail
available). However, this may fail on a Vista/Win7 machine with with ASLR active, because the ASLR base address will usually not equal
ASLR active, because the ASLR base address will usually not equal the preferred base recorded in the dll. In this case, we should make
the preferred base recorded in the dll. In this case, we should the LoadLibraryExW call unconditional.
make the LoadLibraryExW call unconditional.
*/ */
for ( ; d; d = dlls.inext ()) for ( ; d; d = dlls.inext ())
if (d->handle != d->preferred_base) if (d->handle != d->preferred_base)

View File

@ -304,8 +304,8 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
dev.parse (name); dev.parse (name);
else if (strcmp (name, ":sock:") == 0 else if (strcmp (name, ":sock:") == 0
/* NtQueryObject returns an error when called on an LSP socket /* NtQueryObject returns an error when called on an LSP socket
handle. While fdsock now tries to fetch the underlying handle. fdsock tries to fetch the underlying base socket,
base socket, this only works on Vista and later. */ but this might fail. */
|| (strcmp (name, unknown_file) == 0 || (strcmp (name, unknown_file) == 0
&& !::getsockopt ((SOCKET) handle, SOL_SOCKET, SO_RCVBUF, && !::getsockopt ((SOCKET) handle, SOL_SOCKET, SO_RCVBUF,
(char *) &rcv, &len))) (char *) &rcv, &len)))

View File

@ -1888,12 +1888,11 @@ fhandler_disk_file::opendir (int fd)
NFS clients hide dangling symlinks from directory queries, NFS clients hide dangling symlinks from directory queries,
unless you use the FileNamesInformation info class. unless you use the FileNamesInformation info class.
On newer NFS clients (>=Vista) FileIdBothDirectoryInformation FileIdBothDirectoryInformation works fine, but only if the NFS
works fine, but only if the NFS share is mounted to a drive share is mounted to a drive letter. TODO: We don't test that
letter. TODO: We don't test that here for now, but it might here for now, but it might be worth to test if there's a speed
be worth to test if there's a speed gain in using gain in using FileIdBothDirectoryInformation, because it doesn't
FileIdBothDirectoryInformation, because it doesn't require to require to open the file to read the inode number. */
open the file to read the inode number. */
if (pc.hasgood_inode ()) if (pc.hasgood_inode ())
{ {
dir->__flags |= dirent_set_d_ino; dir->__flags |= dirent_set_d_ino;

View File

@ -38,11 +38,11 @@ eval_start_address ()
So we let the heap start at 0x6:00000000L. */ So we let the heap start at 0x6:00000000L. */
uintptr_t start_address = 0x600000000L; uintptr_t start_address = 0x600000000L;
#else #else
/* Starting with Vista, Windows performs heap ASLR. This spoils the entire /* Windows performs heap ASLR. This spoils the entire region below
region below 0x20000000 for us, because that region is used by Windows 0x20000000 for us, because that region is used by Windows to randomize
to randomize heap and stack addresses. Therefore we put our heap into a heap and stack addresses. Therefore we put our heap into a safe region
safe region starting at 0x20000000. This should work right from the start starting at 0x20000000. This should work right from the start in 99%
in 99% of the cases. */ of the cases. */
uintptr_t start_address = 0x20000000L; uintptr_t start_address = 0x20000000L;
if ((uintptr_t) NtCurrentTeb () >= 0xbf000000L) if ((uintptr_t) NtCurrentTeb () >= 0xbf000000L)
{ {

View File

@ -385,7 +385,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol)
and stuff like that. */ and stuff like that. */
&& !is_mvfs (RtlEqualUnicodePathPrefix (&fsname, &ro_u_mvfs, FALSE)) && !is_mvfs (RtlEqualUnicodePathPrefix (&fsname, &ro_u_mvfs, FALSE))
/* NWFS == Novell Netware FS. Broken info class, see below. */ /* NWFS == Novell Netware FS. Broken info class, see below. */
/* NcFsd == Novell Netware FS via own driver since Windows Vista. */ /* NcFsd == Novell Netware FS via own driver. */
&& !is_nwfs (RtlEqualUnicodeString (&fsname, &ro_u_nwfs, FALSE)) && !is_nwfs (RtlEqualUnicodeString (&fsname, &ro_u_nwfs, FALSE))
&& !is_ncfsd (RtlEqualUnicodeString (&fsname, &ro_u_ncfsd, FALSE)) && !is_ncfsd (RtlEqualUnicodeString (&fsname, &ro_u_ncfsd, FALSE))
/* UNIXFS == TotalNet Advanced Server (TAS). Doesn't support /* UNIXFS == TotalNet Advanced Server (TAS). Doesn't support

View File

@ -608,7 +608,7 @@ fdsock (cygheap_fdmanip& fd, const device *dev, SOCKET soc)
handle inheritance. An explanation for this weird behaviour would handle inheritance. An explanation for this weird behaviour would
be nice, though. be nice, though.
NOTE 2. Testing on x86_64 (XP, Vista, 2008 R2, W8) indicates that NOTE 2. Testing on x86_64 (Vista, 2008 R2, W8) indicates that
this is no problem on 64 bit. So we set the default buffer size to this is no problem on 64 bit. So we set the default buffer size to
the default values in current 3.x Linux versions. the default values in current 3.x Linux versions.
@ -1821,8 +1821,8 @@ get_adapters_addresses (PIP_ADAPTER_ADDRESSES *pa_ret, ULONG family)
DWORD ret; DWORD ret;
gaa_wa param = { family, pa_ret }; gaa_wa param = { family, pa_ret };
if ((uintptr_t) &param >= (uintptr_t) 0x80000000L if (wincap.has_gaa_largeaddress_bug ()
&& wincap.has_gaa_largeaddress_bug ()) && (uintptr_t) &param >= (uintptr_t) 0x80000000L)
{ {
/* In Windows Vista and Windows 7 under WOW64, GetAdaptersAddresses fails /* In Windows Vista and Windows 7 under WOW64, GetAdaptersAddresses fails
if it's running in a thread with a stack located in the large address if it's running in a thread with a stack located in the large address
@ -3371,8 +3371,8 @@ cygwin_getaddrinfo (const char *hostname, const char *servname,
| AI_NUMERICSERV | AI_ADDRCONFIG | AI_V4MAPPED | AI_NUMERICSERV | AI_ADDRCONFIG | AI_V4MAPPED
| AI_IDN_MASK))) | AI_IDN_MASK)))
return EAI_BADFLAGS; return EAI_BADFLAGS;
/* AI_NUMERICSERV is not supported prior to Windows Vista. We just check /* AI_NUMERICSERV is not supported "by Microsoft providers". We just
the servname parameter by ourselves here. */ check the servname parameter by ourselves here. */
if (hints && (hints->ai_flags & AI_NUMERICSERV)) if (hints && (hints->ai_flags & AI_NUMERICSERV))
{ {
char *p; char *p;

View File

@ -2889,9 +2889,7 @@ restart:
/* Reparse points are potentially symlinks. This check must be /* Reparse points are potentially symlinks. This check must be
performed before checking the SYSTEM attribute for sysfile performed before checking the SYSTEM attribute for sysfile
symlinks, since reparse points can have this flag set, too. symlinks, since reparse points can have this flag set, too. */
For instance, Vista starts to create a couple of reparse points
with SYSTEM and HIDDEN flags set. */
if ((fileattr & FILE_ATTRIBUTE_REPARSE_POINT)) if ((fileattr & FILE_ATTRIBUTE_REPARSE_POINT))
{ {
res = check_reparse_point (h, fs.is_remote_drive ()); res = check_reparse_point (h, fs.is_remote_drive ());
@ -3974,13 +3972,9 @@ fcwd_access_t::SetVersionFromPointer (PBYTE buf_p, bool is_buffer)
} }
/* This function scans the code in ntdll.dll to find the address of the /* This function scans the code in ntdll.dll to find the address of the
global variable used to access the CWD starting with Vista. While the global variable used to access the CWD. While the pointer is global,
pointer is global, it's not exported from the DLL, unfortunately. it's not exported from the DLL, unfortunately. Therefore we have to
Therefore we have to use some knowledge to figure out the address. use some knowledge to figure out the address. */
This code has been tested on Vista 32/64 bit, Server 2008 32/64 bit,
Windows 7 32/64 bit, Server 2008 R2 (which is only 64 bit anyway),
Windows 8 32/64 bit, Windows 8.1 32/64 bit, and Server 2012 R2. */
#ifdef __x86_64__ #ifdef __x86_64__
@ -4240,9 +4234,8 @@ cwdstuff::override_win32_cwd (bool init, ULONG old_dismount_count)
fast_cwd_ptr = find_fast_cwd (); fast_cwd_ptr = find_fast_cwd ();
if (fast_cwd_ptr) if (fast_cwd_ptr)
{ {
/* Default method starting with Vista. If we got a valid value for /* If we got a valid value for fast_cwd_ptr, we can simply replace
fast_cwd_ptr, we can simply replace the RtlSetCurrentDirectory_U the RtlSetCurrentDirectory_U function entirely. */
function entirely, just as on pre-Vista. */
PVOID heap = peb.ProcessHeap; PVOID heap = peb.ProcessHeap;
/* First allocate a new fcwd_access_t structure on the heap. /* First allocate a new fcwd_access_t structure on the heap.
The new fcwd_access_t structure is 4 byte bigger than the old one, The new fcwd_access_t structure is 4 byte bigger than the old one,
@ -4274,14 +4267,13 @@ cwdstuff::override_win32_cwd (bool init, ULONG old_dismount_count)
} }
else else
{ {
/* This is more a hack, and it's only used on Vista and later if we /* This is more a hack, and it's only used if we failed to find the
failed to find the fast_cwd_ptr value. What we do here is to call fast_cwd_ptr value. We call RtlSetCurrentDirectory_U and let it
RtlSetCurrentDirectory_U and let it set up a new FAST_CWD set up a new FAST_CWD structure. Afterwards, compute the address
structure. Afterwards, compute the address of that structure of that structure utilizing the fact that the buffer address in
utilizing the fact that the buffer address in the user process the user process parameter block is actually pointing to the buffer
parameter block is actually pointing to the buffer in that in that FAST_CWD structure. Then replace the directory handle in
FAST_CWD structure. Then replace the directory handle in that that structure with our own handle and close the original one.
structure with our own handle and close the original one.
Note that the call to RtlSetCurrentDirectory_U also closes our Note that the call to RtlSetCurrentDirectory_U also closes our
old dir handle, so there won't be any handle left open. old dir handle, so there won't be any handle left open.
@ -4374,13 +4366,6 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd)
- SetCurrentDirectory can naturally not work on virtual Cygwin paths - SetCurrentDirectory can naturally not work on virtual Cygwin paths
like /proc or /cygdrive. like /proc or /cygdrive.
Unfortunately, even though we have access to the Win32 process parameter
block, we can't just replace the directory handle. Starting with Vista,
the handle is used elsewhere, and just replacing the handle in the process
parameter block shows quite surprising results.
FIXME: If we ever find a *safe* way to replace the directory handle in
the process parameter block, we're back in business.
Nevertheless, doing entirely without SetCurrentDirectory is not really Nevertheless, doing entirely without SetCurrentDirectory is not really
feasible, because it breaks too many mixed applications using the Win32 feasible, because it breaks too many mixed applications using the Win32
API. API.
@ -4401,11 +4386,11 @@ cwdstuff::set (path_conv *nat_cwd, const char *posix_cwd)
} }
/* Memorize old DismountCount before opening the dir. This value is /* Memorize old DismountCount before opening the dir. This value is
stored in the FAST_CWD structure on Vista and later. It would be stored in the FAST_CWD structure. It would be simpler to fetch the
simpler to fetch the old DismountCount in override_win32_cwd, but old DismountCount in override_win32_cwd, but Windows also fetches
Windows also fetches it before opening the directory handle. It's it before opening the directory handle. It's not quite clear if
not quite clear if that's really required, but since we don't know that's really required, but since we don't know the side effects of
the side effects of this action, we better follow Windows' lead. */ this action, we better follow Windows' lead. */
ULONG old_dismount_count = SharedUserData.DismountCount; ULONG old_dismount_count = SharedUserData.DismountCount;
/* Open a directory handle with FILE_OPEN_FOR_BACKUP_INTENT and with all /* Open a directory handle with FILE_OPEN_FOR_BACKUP_INTENT and with all
sharing flags set. The handle is right now used in exceptions.cc only, sharing flags set. The handle is right now used in exceptions.cc only,

View File

@ -36,12 +36,11 @@ issetugid (void)
return cygheap->user.issetuid () ? 1 : 0; return cygheap->user.issetuid () ? 1 : 0;
} }
/* Starting with Windows Vista, the token returned by system functions /* The token returned by system functions is a restricted token. The full
is a restricted token. The full admin token is linked to it and can admin token is linked to it and can be fetched with NtQueryInformationToken.
be fetched with NtQueryInformationToken. This function returns the original This function returns the elevated token if available, the original token
token on pre-Vista, and the elevated token on Vista++ if it's available, otherwise. The token handle is also made inheritable since that's necessary
the original token otherwise. The token handle is also made inheritable anyway. */
since that's necessary anyway. */
static HANDLE static HANDLE
get_full_privileged_inheritable_token (HANDLE token) get_full_privileged_inheritable_token (HANDLE token)
{ {
@ -219,7 +218,7 @@ get_user_profile_directory (PCWSTR sidstr, PWCHAR path, SIZE_T path_len)
} }
/* Load user profile if it's not already loaded. If the user profile doesn't /* Load user profile if it's not already loaded. If the user profile doesn't
exist on the machine, and if we're running Vista or later, try to create it. exist on the machine try to create it.
Return a handle to the loaded user registry hive only if it got actually Return a handle to the loaded user registry hive only if it got actually
loaded here, not if it already existed. There's no reliable way to know loaded here, not if it already existed. There's no reliable way to know
@ -821,8 +820,8 @@ verify_token (HANDLE token, cygsid &usersid, user_groups &groups, bool *pintern)
/* Check that all groups in the setgroups () list are in the token. /* Check that all groups in the setgroups () list are in the token.
A token created through ADVAPI should be allowed to contain more A token created through ADVAPI should be allowed to contain more
groups than requested through setgroups(), especially since Vista groups than requested through setgroups(), especially since the
and the addition of integrity groups. */ addition of integrity groups. */
memset (saw, 0, sizeof(saw)); memset (saw, 0, sizeof(saw));
for (int gidx = 0; gidx < groups.sgsids.count (); gidx++) for (int gidx = 0; gidx < groups.sgsids.count (); gidx++)
{ {

View File

@ -628,11 +628,6 @@ _recycler_sd (void *buf, bool users, bool dir)
return NULL; return NULL;
RtlCreateSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION); RtlCreateSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION);
PACL dacl = (PACL) (psd + 1); PACL dacl = (PACL) (psd + 1);
/* Pre-Vista, the per-user recycler dir has a rather too complicated
ACL by default, which has distinct ACEs for inheritable and non-inheritable
permissions. However, this ACL is practically equivalent to the ACL
created since Vista. Therefore we simplify our job here and create the
pre-Vista permissions the same way as on Vista and later. */
RtlCreateAcl (dacl, MAX_DACL_LEN (3), ACL_REVISION); RtlCreateAcl (dacl, MAX_DACL_LEN (3), ACL_REVISION);
RtlAddAccessAllowedAceEx (dacl, ACL_REVISION, RtlAddAccessAllowedAceEx (dacl, ACL_REVISION,
dir ? SUB_CONTAINERS_AND_OBJECTS_INHERIT dir ? SUB_CONTAINERS_AND_OBJECTS_INHERIT

View File

@ -89,7 +89,6 @@ void uinfo_init ();
#define SE_MANAGE_VOLUME_PRIVILEGE 28U #define SE_MANAGE_VOLUME_PRIVILEGE 28U
#define SE_IMPERSONATE_PRIVILEGE 29U #define SE_IMPERSONATE_PRIVILEGE 29U
#define SE_CREATE_GLOBAL_PRIVILEGE 30U #define SE_CREATE_GLOBAL_PRIVILEGE 30U
/* Starting with Vista */
#define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE 31U #define SE_TRUSTED_CREDMAN_ACCESS_PRIVILEGE 31U
#define SE_RELABEL_PRIVILEGE 32U #define SE_RELABEL_PRIVILEGE 32U
#define SE_INCREASE_WORKING_SET_PRIVILEGE 33U #define SE_INCREASE_WORKING_SET_PRIVILEGE 33U

View File

@ -268,11 +268,11 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access, ULONG flags)
them into the recycler. */ them into the recycler. */
if (pfni->FileNameLength == 2) /* root dir. */ if (pfni->FileNameLength == 2) /* root dir. */
goto out; goto out;
/* The recycler name on Vista and later is $Recycler.Bin by default. If the /* The recycler name is $Recycler.Bin by default. If the recycler dir
recycler dir disappeared for some reason, the shell32.dll recreates the disappeared for some reason, the shell32.dll recreates the directory in
directory in all upper case. So, we never know beforehand if the dir all upper case. So, we never know beforehand if the dir is written in
is written in mixed case or in all upper case. That's a problem when mixed case or in all upper case. That's a problem when using
using casesensitivity. If the file handle given to FileRenameInformation casesensitivity. If the file handle given to FileRenameInformation
has been opened casesensitive, the call also handles the path to the has been opened casesensitive, the call also handles the path to the
target dir casesensitive. Rather then trying to find the right name target dir casesensitive. Rather then trying to find the right name
of the recycler, we just reopen the file to move with OBJ_CASE_INSENSITIVE, of the recycler, we just reopen the file to move with OBJ_CASE_INSENSITIVE,
@ -958,10 +958,10 @@ try_again:
"Subsequently, the only legal operation by such a caller is "Subsequently, the only legal operation by such a caller is
to close the open file handle." to close the open file handle."
FIXME? On Vista and later, we could use FILE_HARD_LINK_INFORMATION FIXME? We could use FILE_HARD_LINK_INFORMATION to find all
to find all hardlinks and use one of them to restore the R/O bit, hardlinks and use one of them to restore the R/O bit, after the
after the NtClose, but before we stop the transaction. This NtClose, but before we stop the transaction. This avoids the
avoids the aforementioned problem entirely . */ aforementioned problem entirely . */
else if (pc.is_lnk_symlink () && num_links > 1) else if (pc.is_lnk_symlink () && num_links > 1)
NtSetAttributesFile (fh, pc.file_attributes ()); NtSetAttributesFile (fh, pc.file_attributes ());
} }
@ -3219,9 +3219,9 @@ seteuid32 (uid_t uid)
CW_TOKEN_RESTRICTED); CW_TOKEN_RESTRICTED);
setuid (getuid ()); setuid (getuid ());
Note that using the current uid is a requirement! Starting with Windows Note that using the current uid is a requirement! We have restricted
Vista, we have restricted tokens galore (UAC), so this is really just tokens galore (UAC), so this is really just a special case to restrict
a special case to restict your own processes to lesser rights. */ your own processes to lesser rights. */
bool request_restricted_uid_switch = (uid == myself->uid bool request_restricted_uid_switch = (uid == myself->uid
&& cygheap->user.ext_token_is_restricted); && cygheap->user.ext_token_is_restricted);
if (uid == myself->uid && !cygheap->user.groups.ischanged if (uid == myself->uid && !cygheap->user.groups.ischanged