From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2155) id 2735D3858CD1; Mon, 11 Mar 2024 16:21:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2735D3858CD1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1710174107; bh=+NbyGtsR829KjBB6Y16vQvp8BRzA30TKaZ29vh6iq18=; h=From:To:Subject:Date:From; b=NkUSWVb1L4hloe/ch8GRuVUTH4Jlq/1JkLkaa4RAT5dsD3ynSbiUCOFjOfALIKeFe jb8+owGy3mOiADqRKdfS8UFSBtW6f9zde6q8ITUF4R9E9k94qW/VjHJzgCBIflmApD HALCtxCkdEcVqxmbh6ReO04eekA2pAbsPPrWjSv4= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Corinna Vinschen To: cygwin-cvs@sourceware.org Subject: [newlib-cygwin/cygwin-3_5-branch] Cygwin: try to avoid recalling offline files X-Act-Checkin: newlib-cygwin X-Git-Author: Corinna Vinschen X-Git-Refname: refs/heads/cygwin-3_5-branch X-Git-Oldrev: f6be372ace889afa12163bd2c8a9cb717d7eff85 X-Git-Newrev: c1cf14a871528d1adba88a0128813b58d52ba926 Message-Id: <20240311162147.2735D3858CD1@sourceware.org> Date: Mon, 11 Mar 2024 16:21:47 +0000 (GMT) List-Id: https://sourceware.org/git/gitweb.cgi?p=3Dnewlib-cygwin.git;h=3Dc1cf14a8715= 28d1adba88a0128813b58d52ba926 commit c1cf14a871528d1adba88a0128813b58d52ba926 Author: Corinna Vinschen AuthorDate: Fri Mar 8 20:57:06 2024 +0100 Commit: Corinna Vinschen CommitDate: Mon Mar 11 15:29:32 2024 +0100 Cygwin: try to avoid recalling offline files =20 Chances are high that Cygwin recalls offline files from remote storage, even if the file is only accessed during stat(2) or readdir(3). =20 To avoid this - make sure Cygwin is placeholder-aware, - open files in path_conv handling, as well as in stat(2)/readdir(3) scenarios with FILE_OPEN_NO_RECALL, and - during symlink checking or testing for executablility, don't even try to open the file if one of the OFFLINE attributes is set. =20 Reported-by: Marcin Wisnicki Signed-off-by: Corinna Vinschen Diff: --- winsup/cygwin/autoload.cc | 1 + winsup/cygwin/dcrt0.cc | 3 +++ winsup/cygwin/fhandler/disk_file.cc | 20 ++++++++++++++------ winsup/cygwin/local_includes/ntdll.h | 8 ++++++++ winsup/cygwin/local_includes/path.h | 16 +++++++++++++++- winsup/cygwin/local_includes/winlean.h | 7 +++++++ winsup/cygwin/path.cc | 17 +++++++++++++---- 7 files changed, 61 insertions(+), 11 deletions(-) diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 65e906e8b9d0..cc9dafe1b621 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -479,6 +479,7 @@ LoadDLLfuncEx (SetThreadDescription, KernelBase, 1) LoadDLLfunc (VirtualAlloc2, KernelBase) =20 LoadDLLfunc (NtMapViewOfSectionEx, ntdll) +LoadDLLfuncEx (RtlSetProcessPlaceholderCompatibilityMode, ntdll, 1) =20 LoadDLLfunc (ldap_bind_s, wldap32) LoadDLLfunc (ldap_count_entries, wldap32) diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc index fc1eec76a4a5..ea6a18b51d70 100644 --- a/winsup/cygwin/dcrt0.cc +++ b/winsup/cygwin/dcrt0.cc @@ -809,6 +809,9 @@ dll_crt0_1 (void *) if (dynamically_loaded) sigproc_init (); =20 + /* Call this before accessing any files. */ + RtlSetProcessPlaceholderCompatibilityMode (PHCM_EXPOSE_PLACEHOLDERS); + check_sanity_and_sync (user_data); =20 /* Initialize malloc and then call user_shared_initialize since it relies diff --git a/winsup/cygwin/fhandler/disk_file.cc b/winsup/cygwin/fhandler/d= isk_file.cc index d08fe9160d35..f3592148fc5b 100644 --- a/winsup/cygwin/fhandler/disk_file.cc +++ b/winsup/cygwin/fhandler/disk_file.cc @@ -176,7 +176,9 @@ readdir_check_reparse_point (POBJECT_ATTRIBUTES attr, b= ool remote) bool ret =3D false; =20 status =3D NtOpenFile (&reph, READ_CONTROL, attr, &io, FILE_SHARE_VALID_= FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT); + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT + | FILE_OPEN_REPARSE_POINT); if (NT_SUCCESS (status)) { PREPARSE_DATA_BUFFER rp =3D (PREPARSE_DATA_BUFFER) tp.c_get (); @@ -328,6 +330,7 @@ fhandler_base::fstat_by_name (struct stat *buf) status =3D NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_NO_RECALL | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); if (!NT_SUCCESS (status)) @@ -616,7 +619,8 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs) opened =3D NT_SUCCESS (NtOpenFile (&fh, READ_CONTROL, pc.get_object_attr (attr, sec_none_nih), &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT)); + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT)); if (!opened) { /* Can't open file. Try again with parent dir. */ @@ -625,7 +629,8 @@ fhandler_disk_file::fstatvfs (struct statvfs *sfs) attr.ObjectName =3D &dirname; opened =3D NT_SUCCESS (NtOpenFile (&fh, READ_CONTROL, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT)); + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT)); if (!opened) goto out; } @@ -2323,7 +2328,8 @@ readdir_get_ino (const char *path, bool dot_dot) || NT_SUCCESS (NtOpenFile (&hdl, READ_CONTROL, pc.get_object_attr (attr, sec_none_nih), &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT | (pc.is_known_reparse_point () ? FILE_OPEN_REPARSE_POINT : 0))) ) @@ -2372,8 +2378,9 @@ fhandler_disk_file::readdir_helper (DIR *dir, dirent = *de, DWORD w32_err, Mountpoints and unknown or unhandled reparse points will be treated as normal file/directory/unknown. In all cases, returning the INO of the reparse point (not of the target) matches behavior of posix syste= ms. + Unless the file is OFFLINE. *. */ - if (attr & FILE_ATTRIBUTE_REPARSE_POINT) + if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) && !isoffline (attr)) { OBJECT_ATTRIBUTES oattr; =20 @@ -2618,7 +2625,8 @@ go_ahead: &nfs_aol_ffei, sizeof nfs_aol_ffei) : NtOpenFile (&hdl, READ_CONTROL, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT); if (NT_SUCCESS (f_status)) { diff --git a/winsup/cygwin/local_includes/ntdll.h b/winsup/cygwin/local_inc= ludes/ntdll.h index 9605784e32a8..7737ae503c18 100644 --- a/winsup/cygwin/local_includes/ntdll.h +++ b/winsup/cygwin/local_includes/ntdll.h @@ -169,6 +169,13 @@ extern GUID __cygwin_socket_guid; #define FILE_VC_QUOTAS_REBUILDING 0x00000200 #define FILE_VC_VALID_MASK 0x000003ff =20 +#define PHCM_APPLICATION_DEFAULT 0 +#define PHCM_DISGUISE_PLACEHOLDER 1 +#define PHCM_EXPOSE_PLACEHOLDERS 2 +#define PHCM_MAX 2 +#define PHCM_ERROR_INVALID_PARAMETER -1 +#define PHCM_ERROR_NO_TEB -2 + /* IOCTL code to impersonate client of named pipe. */ =20 #define FSCTL_PIPE_DISCONNECT CTL_CODE(FILE_DEVICE_NAMED_PIPE, 1, \ @@ -1639,6 +1646,7 @@ extern "C" BOOLEAN); NTSTATUS RtlSetGroupSecurityDescriptor (PSECURITY_DESCRIPTOR, PSID, BOOL= EAN); NTSTATUS RtlSetOwnerSecurityDescriptor (PSECURITY_DESCRIPTOR, PSID, BOOL= EAN); + CHAR RtlSetProcessPlaceholderCompatibilityMode (CHAR); PUCHAR RtlSubAuthorityCountSid (PSID); PULONG RtlSubAuthoritySid (PSID, ULONG); ULONG RtlUnicodeStringToAnsiSize (PUNICODE_STRING); diff --git a/winsup/cygwin/local_includes/path.h b/winsup/cygwin/local_incl= udes/path.h index d19721e0cd3f..cd0cc8a41256 100644 --- a/winsup/cygwin/local_includes/path.h +++ b/winsup/cygwin/local_includes/path.h @@ -23,6 +23,14 @@ has_attribute (DWORD attributes, DWORD attribs_to_test) && (attributes & attribs_to_test); } =20 +extern inline bool +isoffline (DWORD attributes) +{ + return has_attribute (attributes, FILE_ATTRIBUTE_OFFLINE + | FILE_ATTRIBUTE_RECALL_ON_OPEN + | FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS); +} + enum executable_states { is_executable, @@ -236,6 +244,12 @@ class path_conv bool exists () const {return fileattr !=3D INVALID_FILE_ATTRIBUTES;} bool has_attribute (DWORD x) const {return exists () && (fileattr & x);} int isdir () const {return has_attribute (FILE_ATTRIBUTE_DIRECTORY);} + bool isoffline () const + { + return has_attribute (FILE_ATTRIBUTE_OFFLINE + | FILE_ATTRIBUTE_RECALL_ON_OPEN + | FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS); + } executable_states exec_state () { extern int _check_for_executable; @@ -243,7 +257,7 @@ class path_conv return is_executable; if (mount_flags & MOUNT_NOTEXEC) return not_executable; - if (!_check_for_executable) + if (isoffline () || !_check_for_executable) return dont_care_if_executable; return dont_know_if_executable; } diff --git a/winsup/cygwin/local_includes/winlean.h b/winsup/cygwin/local_i= ncludes/winlean.h index 113b2c6b0d3f..947109bdeee4 100644 --- a/winsup/cygwin/local_includes/winlean.h +++ b/winsup/cygwin/local_includes/winlean.h @@ -97,6 +97,13 @@ details. */ #define FILE_SUPPORTS_GHOSTING 0x40000000 #endif =20 +#ifndef FILE_ATTRIBUTE_RECALL_ON_OPEN +#define FILE_ATTRIBUTE_RECALL_ON_OPEN 0x00040000 +#endif +#ifndef FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS +#define FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS 0x00400000 +#endif + /* So-called "Microsoft Account" SIDs (S-1-11-...) have a netbios domain n= ame "MicrosoftAccounts". The new "Application Container SIDs" (S-1-15-...) have a netbios domain name "APPLICATION PACKAGE AUTHORITY" diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index b8e5746fdd2a..c0d62e5654b4 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -576,6 +576,7 @@ getfileattr (const char *path, bool caseinsensitive) /*= path has to be always ab status =3D NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, &attr, &io, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_NO_RECALL | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); if (NT_SUCCESS (status)) @@ -3191,7 +3192,8 @@ restart: } status =3D NtOpenFile (&h, READ_CONTROL | FILE_READ_ATTRIBUTES, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_REPARSE_POINT + FILE_OPEN_NO_RECALL + | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT); debug_printf ("%y =3D NtOpenFile (no-EAs %S)", status, &upath); } @@ -3319,6 +3321,7 @@ restart: status =3D NtOpenFile (&dir, SYNCHRONIZE | FILE_LIST_DIRECTORY, &dattr, &io, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT + | FILE_OPEN_NO_RECALL | FILE_OPEN_FOR_BACKUP_INTENT | FILE_DIRECTORY_FILE); if (!NT_SUCCESS (status)) @@ -3408,7 +3411,11 @@ restart: directory using a relative path, symlink evaluation goes totally awry. We never want a virtual drive evaluated as symlink. */ if (upath.Length <=3D 14) - goto file_not_symlink; + goto file_not_symlink; + + /* Offline files, even if reparse points, are not symlinks. */ + if (isoffline (fileattr)) + goto file_not_symlink; =20 /* Reparse points are potentially symlinks. This check must be performed before checking the SYSTEM attribute for sysfile @@ -3454,7 +3461,8 @@ restart: =20 status =3D NtOpenFile (&sym_h, SYNCHRONIZE | GENERIC_READ, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT); if (!NT_SUCCESS (status)) res =3D 0; @@ -3508,7 +3516,8 @@ restart: =20 status =3D NtOpenFile (&sym_h, SYNCHRONIZE | GENERIC_READ, &attr, &io, FILE_SHARE_VALID_FLAGS, - FILE_OPEN_FOR_BACKUP_INTENT + FILE_OPEN_NO_RECALL + | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT); =20 if (!NT_SUCCESS (status))