Commit 649911fb40 avoids the
calls to NetUserGetGroups and NetUserGetLocalGroups since
these can take a lot of time. The same problem potentially
occurs when loading the user profile. The code fetches
the roaming profile path calling NetUserGetInfo, which also
can be rather slow.
To avoid this problem, fetch the profile patch using LDAP.
Also, don't bail out early if the user's registry hive already
exists. This may result in outdated information.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
NetUserGetGroups and NetUserGetLocalGroups sometimes take a lot of time
(up to more than 2 mins) for no apparent reason.
Call s4uauth to generate an identification token for the user and fetch
the group list from there. This is *much* faster.
Keep the old code only for the sake of WOW64 on Vista and Windows 7,
which don't implement MsV1_0S4ULogon.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
s4uath was only callable to create an impersonation token so
far. Rework the function to allow creating an identification
token for informational purposes even from untrusted processes.
Take domainname and username instead of a passwd pointer to be
more multi-purpose.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Commit 4e34a39b5c made sure all user and
group names are case-correct, but it introduced a hefty performance hit
on starting the first Cygwin process.
Adding an ldap call for each AD group in a user token takes its toll in
bigger AD environments with lots of groups in a user token. Real-life
example: 300 groups w/ roundtrip time to the LDAP server of 0.25 secs
per call...
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Up to Vista CreateProcessAsUser only worked with primary tokens,
so convert S4U impersonation token to primary token. MSDN still
documents it that way, but actually an impersonation token is
sufficient since Windows 7.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Under WOW64 on 64 bit Windows 7, MsV1_0S4ULogon appears to be
unimplemented, probably under Vista as well. Re-enable
create_token method, to allow basic seteuid on W7 WOW64 and
Vista as well.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
for domain accounts we try KerbS4ULogon first, MsV1_0S4ULogon
second. But we only fetch the package id for the supporting
authentication package (Kerberos/MsV1_0) once at the start.
Duplicate LsaLookupAuthenticationPackage call and move into the
Kerb/MsV1_0 branches so that it fetches the correct package id
for the method we call next.
Curious enough this worked before. Apparently both methods
work with the MICROSOFT_KERBEROS_NAME_A package id. However,
requesting and using the right authentication package id is
the prudent thing to do.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This reverts commit 7c34811440.
This potentially allows to circumvent OpenSSHs user/group name matching,
unless the Admin knows to add every local user twice or to use patterns,
e.g.:
Match user MACHINE+user,.+user
Match user *+user
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Commit c1023ee353 changed the way
path_conv::binmode() works. Rather than returning three states,
O_BINARY, O_TEXT, 0, it only returned 2 states, O_BINARY, O_TEXT. Since
mounts are only binary if they are explicitely mounted binary by setting
the MOUNT_BINARY flag, textmode is default.
This introduced a new bug. When inheriting stdio HANDLEs from native
Windows processes, the fhandler and its path_conv are created from a
device struct only. None of the path or mount flags get set this way.
So the mount flags are 0 and path_conv::binmode() returned 0.
After the path_conv::binmode() change it returned O_TEXT since, as
explained above, the default mount mode is textmode.
Rather than just enforcing binary mode for path_conv's created from
device structs, this patch changes the default mount mode to binary:
Replace MOUNT_BINARY flag with MOUNT_TEXT flag with opposite meaning.
Drop all explicit setting of MOUNT_BINARY. Drop local set_flags
function, it doesn't add any value.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
When recognizing a negative pid, optind is off by one. The
code correcting this has been erroneously removed by commit
8de660271f. Revert that.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
The solution from commit 9a3cc77b2a
didn't work for foreign domain accounts. Rather than calling
LookupAccountSid we now use the info when we fetch it anyway
via LDAP or Net*GetInfo. Only in case of domain groups we have
to add an LDAP call explicitly.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Make sure a domain+username fits into the local name buffer.
The former buffer size didn't take adding a domain name to
a really_really_long_user_name into account.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
When looking up valid accounts by name, LookupAccountName returns
a SID and a case-correct domain name. However, the name was input
and LookupAccountName is case-insensitive, so the name is not
necessarily written the same way as in SAM or AD.
Fix that by doing a reverse lookup on the just fetched SID. This
fetches the account name in the correct case. Override the
incoming name with the case correct name from LookupAccountSid.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
The M class cores don't support Semihosting v2 mixed mode, but we were
accidentally using the new immediates for it. My last patch changed the
immediates which broke the build because doing a full multi-lib build
including M architectures now results in an assembler error instead of
silently doing the wrong thing.
This fixes the issue by changing the defines around such that According
to the specs any M class build uses the normal semihosting instructions.
Regtested on arm-none-eabi and no issues, using a build with m class
multilibs too.
This is a really old and crappy API, as the previous commit shows.
Use NtQueryInformationFile(FilePositionInformation) here instead.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
dtable::set_file_pointers_for_exec is called from
child_info_spawn::worker to move the file position of O_APPEND
files to EOF if the child is a native child.
However, this only works correctly for the first O_APPEND
file descriptor:
- set_file_pointers_for_exec calls SetFilePointer. The higher
4 bytes of the desired file offset are given to SetFilePointer
as pointer to a DWORD value. On return, SetFilePointer returns
the higher 4 bytes of the new file position in this DWORD.
- So for the second and subsequent descriptors the higher 4 byte
of the file position depend on what the actual file position
of the previous file has been set to:
- If the file is > 2 Gigs, the high offset will not be 0 anymore.
- If the desciptor points to a non-seekable file (i.e., a pipe
or socket), SetFilePosition returns an error and sets the high
position to -1.
Fix this by calling SetFilePointerEx instead, which does not
modify the incoming position value.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
When calling spawnve, in contrast to execve, the parent has
to create the pid for the child. With the old technique
this was simply the Windows pid, but now we have to inform
the child about its new pid.
Add a cygpid member to class child_info_spawn. Set it in
child_info_spawn::worker, just prior to calling CreateProcess
rather than afterwards. Overwrite cygheap->pid in
child_info_spawn::handle_spawn before calling pinfo::thisproc.
Make sure pinfo::thisproc knows the pid is already set by
setting the handle argument to INVALID_HANDLE_VALUE.
Also set procinfo->dwProcessId to myself_initial.dwProcessId
instead of to myself_initial.pid for clarity.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
The Semihosting v2 protocol requires us to output the Armv8-a HLT instruction
when in mixed mode (SEMIHOST_V2_MIXED_MODE), however it also requires this to
be done for Armv7-a and earlier architectures.
The HLT instruction is defined in the undefined encoding space for older
architectures but simulators such as QEMU already trap on it [1] for all
architectures and is a requirement for semihosting v2 [2].
Unfortunately the GAS restricts the use of HLT to Armv8-a which requires us to
use the instruction encodings we want directly in crt0.
This patch does this, I have not updated newlib/libc/* as that is quite out of
date already. A proper sync is needed in order to get things back in sync.
A different patch for this would be best.
[1] 19a6e31c9d
[2] https://developer.arm.com/docs/100863/latest/the-semihosting-interface
When the current process has renamed (to bin) a readonly dll, we get
STATUS_TRANSACTION_NOT_ACTIVE for unknown reason when subsequently
creating the forkable hardlink. A workaround is to open the original
file with FILE_WRITE_ATTRIBUTES access, but that fails with permission
denied for users not owning the original file.
* forkable.cc (dll::create_forkable): Retry hardlink creation using the
original file's handle opened with FILE_WRITE_ATTRIBUTES access when the
first attempt fails with STATUS_TRANSACTION_NOT_ACTIVE.
* Rename cygwin_shared->prefer_forkable_hardlinks to
forkable_hardlink_support, with values
0 for Unknown, 1 for Supported, -1 for Unsupported.
Upon first dll loaded ever, dll_list::forkable_ntnamesize checks the
/var/run/cygfork directory to both exist and reside on NTFS, setting
cygwin_shared->forkable_hardlink_support accordingly.
* Replace enum forkables_needs by bool forkables_created: Set
to True by request_forkables after creating forkable hardlinks.
To avoid the need for each process to check the filesystem to detect
that hardlink creation is impossible or disabled, cache this fact in
shared memory. Removing cygfork directory while in use does disable
hardlinks creation. To (re-)enable hardlinks creation, the cygfork
directory has to exist before the first cygwin process does fork.
* forkable.cc (dll_list::forkable_ntnamesize): Short cut
forkables needs to impossible when disabled via shared memory.
(dll_list::update_forkables_needs): When detecting hardlink
creation as impossible (not on NTFS) while still (we are the
first one checking) enabled via shared memory, disable the
shared memory value.
(dll_list::request_forkables): Disable the shared memory value
when hardlinks creation became disabled, that is when the
cygfork directory was removed.
* include/cygwin/version.h: Bump CYGWIN_VERSION_SHARED_DATA 6.
* shared_info.h (struct shared_info): Add member
prefer_forkable_hardlinks. Update CURR_SHARED_MAGIC.
* shared.cc (shared_info::initialize): Initialize
prefer_forkable_hardlinks to 1 (Yes).
To support in-cygwin package managers, the fork() implementation must
not rely on .exe and .dll files to stay in their original location, as
the package manager's job is to replace these files. Instead, when the
first fork try fails, and we have NTFS, we use hardlinks to the original
binaries in /var/run/cygfork/ to create the child process during the
second fork try, along the main.exe.local file to enable the "DotLocal
Dll Redirection" feature for the dlls.
The (probably few) users that need an update-safe fork manually have to
create the /var/run/cygfork/ directory for now, using:
mkdir --mode=a=rwxt /var/run/cygfork
* child_info.h: Bump CURR_CHILD_INFO_MAGIC.
(enum child_status): Add _CI_SILENTFAIL flag.
(struct child_info): Add silentfail setter and getter.
* winsup.h (child_copy): Add bool silentfail parameter.
* cygheap.cc: Pass silentfail parameter to child_copy.
* dcrt0.cc: Ditto.
* dll_init.h (struct dll): Define public inline method forkedntname.
(struct dll_list): Declare private method find_by_forkedntname.
* dll_init.cc (struct dll_list): Implement find_by_forkedntname.
(dll_list::alloc): Use find_by_forkedntname when in load after fork.
(dll_list::load_after_fork_impl): Load dlls using dll::forkedntname.
* fork.cc (frok::parent): Set silentfail child info flag. Pass
silentfail parameter to child_copy. Use forkedntname of
dlls.main_executable.
(fork): When first dofork run failed and did not use forkables,
run dofork again with_forkables set to true.
(child_copy): Use debug_printf if silentfail is true,
system_printf otherwise.
In preparation to protect fork() against dll- and exe-updates, create
hardlinks to the main executable and each loaded dll in subdirectories
of /var/run/cygfork/, if that one exists on the NTFS file system.
The directory names consist of the user sid, the main executable's NTFS
IndexNumber, and the most recent LastWriteTime of all involved binaries
(dlls and main executable). Next to the main.exe hardlink we create the
empty file main.exe.local to enable dll redirection.
The name of the mutex to synchronize hardlink creation/cleanup also is
assembled from these directory names, to allow for synchronized cleanup
of even orphaned hardlink directories.
The hardlink to each dynamically loaded dll goes into another directory,
named using the NTFS IndexNumber of the dll's original directory.
* Makefile.in (DLL_OFILES): Add forkable.o.
* dll_init.h (struct dll): Declare member variables fbi, fii,
forkable_ntname. Declare methods nominate_forkable,
create_forkable.
(struct dll_list): Declare enum forkables_needs. Declare member
variables forkables_dirx_size, forkables_dirx_ntname,
forkables_mutex_name, forkables_mutex. Declare private methods
forkable_ntnamesize, prepare_forkables_nomination,
update_forkables_needs, update_forkables, create_forkables,
denominate_forkables, close_mutex, try_remove_forkables,
set_forkables_inheritance, request_forkables. Declare public
static methods ntopenfile, read_fii, read_fbi. Declare public
methods release_forkables, cleanup_forkables. Define public
inline method setup_forkables.
* dll_init.cc (dll_list::alloc): Allocate memory to hold the
name of the hardlink in struct dll member forkable_ntname.
Initialize struct dll members fbi, fii.
(dll_list::load_after_fork): Call release_forkables method.
* fork.cc: Rename public fork function to static dofork, add
with_forkables as bool pointer parameter. Add new fork function
calling dofork. (struct frok): Add bool pointer member
with_forkables, add as constructor parameter.
(frok::parent): Call dlls.setup_forkables before CreateProcessW,
dlls.release_forkables afterwards.
* pinfo.cc (pinfo::exit): Call dlls.cleanup_forkables.
* syscalls.cc (_unlink_nt): Rename public unlink_nt function to
static _unlink_nt, with 'shareable' as additional argument.
(unlink_nt): New, wrap _unlink_nt for original behaviour.
(unlink_nt_shareable): New, wrap _unlink_nt to keep a binary
file still loadable while removing one of its hardlinks.
* forkable.cc: New file.
Implement static functions mkdirs, rmdirs, rmdirs_synchronized,
stat_real_file_once, format_IndexNumber, rootname, sidname,
exename, lwtimename. Define static array forkable_nameparts.
(struct dll): Implement nominate_forkable, create_forkable.
(struct dll_list): Implement static methods ntopenfile,
read_fii, read_fbi. Implement forkable_ntnamesize,
Even for the main executable and cygwin1.dll store the file name as full
NT path. Create the child process using the main executable's file name
converted from the full NT path stored before.
* dll_init.cc (dll_list::alloc): Search for DLL_SELF type entry
with module name like for DLL_LINK, use full NT path to search
for DLL_LOAD type only. For DLL_SELF type do not indicate
having a destructor to be called.
(dll_list::find): Ignore DLL_SELF type entries.
(dll_list::init): Ditto. Call track_self method.
(dll_list::track_self): New.
(dll_list::load_after_fork): Call track_self method.
* dll_init.h (enum dll_type): Add DLL_SELF, for the main
executable and cygwin1.dll.
(struct dll_list): Declare private method track_self. Declare
member variable main_executable.
* fork.cc (frok::parent): Use ntname from dlls.main_executable
to create child process, converted to short path using
dll_list::buffered_shortname.
Store loaded dll's file name as full NT path.
* dll_init.h (struct dll): Rename member variable name to ntname.
(struct dll_list): Declare private static member variable
nt_max_path_buffer. Declare public static methods form_ntname,
form_shortname. Define public static methods nt_max_path_buf,
buffered_shortname.
(dll_list::operator []): Use PCWCHAR rather than const PWCHAR.
(dll_list::find_by_modname): Ditto.
* dll_init.cc (in_load_after_fork): Define earlier in file.
(struct dll_list): Rename member variable name to ntname.
Define nt_max_path_buffer variable.
Implement static methods form_ntname, form_shortname.
(dll_list::operator []): Use PCWCHAR rather than const PWCHAR.
(dll_list::find_by_modname): Ditto.
(reserve_at): Ditto.
(release_at): Ditto.
(dll_list::alloc): Use nt_max_path_buf method instead of local
buffer. Store module file name as full NT path, convert using
the form_ntname static method.
(dll_list::load_after_fork): Call load_after_fork_impl only when
reload_on_fork is set.
* fork.cc (frok::child): Call dlls.load_after_fork even without
need to dynamically load dlls.
(frok::parent): Move syscall_printf into the retry loop.