diff options
-rw-r--r-- | winsup/cygwin/ChangeLog | 28 | ||||
-rw-r--r-- | winsup/cygwin/globals.cc | 1 | ||||
-rw-r--r-- | winsup/cygwin/mount.cc | 1 | ||||
-rw-r--r-- | winsup/cygwin/mount.h | 2 | ||||
-rw-r--r-- | winsup/cygwin/ntdll.h | 4 | ||||
-rw-r--r-- | winsup/cygwin/path.h | 1 | ||||
-rw-r--r-- | winsup/cygwin/sec_helper.cc | 60 | ||||
-rw-r--r-- | winsup/cygwin/security.cc | 14 | ||||
-rw-r--r-- | winsup/cygwin/security.h | 7 | ||||
-rw-r--r-- | winsup/cygwin/syscalls.cc | 48 |
10 files changed, 143 insertions, 23 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 03bebcf40..02e6931bf 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,31 @@ +2012-06-03 Corinna Vinschen <corinna@vinschen.de> + + * globals.cc (ro_u_refs): New R/O unicode string. + * mount.cc (fs_info::update): Recognize ReFS. + * mount.h (enum fs_info_type): Add refs. + (class fs_info): Add refs flag and accessor methods. + * ntdll.h (RtlAddAccessAllowedAceEx): Declare. + (RtlAddAccessDeniedAceEx): Declare. + * path.h (path_conv::fs_is_refs): Define. + * sec_helper.cc (_recycler_sd): New function to create security + descriptors suitable for the recycler bin starting with Vista. + * security.cc (add_access_allowed_ace): Use RtlAddAccessAllowedAceEx + and drop code to set AceFlags explicitely. + (add_access_denied_ace): Use RtlAddAccessDeniedAceEx and drop code to + set AceFlags explicitely. + * security.h (_recycler_sd): Declare. + (recycler_sd): Define. + * syscalls.cc (desktop_ini): Change formatting. + (desktop_ini_ext): Define third line of recycler desktop.ini file + since Vista, + (try_to_bin): Handle ReFS just like NTFS. Write Vista and later + Recycler in all uppercase, just like shell32 does when recreating it. + Fix comments to include ReFS. Don't implicitely reuse object + attributes from earlier NtOpenFile call, rather recreate it for safety. + Use recycler_sd call when creating security descriptor for Recycler + dirs and files on Vista and later. Write third line of desktop.ini + when on Vista and later. + 2012-06-03 Christopher Faylor <me.cygwin2012@cgf.cx> * winbase.h: Add missing copyright date. diff --git a/winsup/cygwin/globals.cc b/winsup/cygwin/globals.cc index 9bce8f395..05a3c390b 100644 --- a/winsup/cygwin/globals.cc +++ b/winsup/cygwin/globals.cc @@ -107,6 +107,7 @@ UNICODE_STRING _RDATA ro_u_fat = _ROU (L"FAT"); UNICODE_STRING _RDATA ro_u_mvfs = _ROU (L"MVFS"); UNICODE_STRING _RDATA ro_u_nfs = _ROU (L"NFS"); UNICODE_STRING _RDATA ro_u_ntfs = _ROU (L"NTFS"); +UNICODE_STRING _RDATA ro_u_refs = _ROU (L"ReFS"); UNICODE_STRING _RDATA ro_u_sunwnfs = _ROU (L"SUNWNFS"); UNICODE_STRING _RDATA ro_u_udf = _ROU (L"UDF"); UNICODE_STRING _RDATA ro_u_unixfs = _ROU (L"UNIXFS"); diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index ddbccae21..a661b8731 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -402,6 +402,7 @@ fs_info::update (PUNICODE_STRING upath, HANDLE in_vol) if (!got_fs () && !is_ntfs (RtlEqualUnicodeString (&fsname, &ro_u_ntfs, FALSE)) && !is_fat (RtlEqualUnicodePathPrefix (&fsname, &ro_u_fat, TRUE)) + && !is_refs (RtlEqualUnicodeString (&fsname, &ro_u_refs, FALSE)) && !is_csc_cache (RtlEqualUnicodeString (&fsname, &ro_u_csc, FALSE)) && is_cdrom (ffdi.DeviceType == FILE_DEVICE_CD_ROM)) is_udf (RtlEqualUnicodeString (&fsname, &ro_u_udf, FALSE)); diff --git a/winsup/cygwin/mount.h b/winsup/cygwin/mount.h index 187972464..1d3b7451b 100644 --- a/winsup/cygwin/mount.h +++ b/winsup/cygwin/mount.h @@ -29,6 +29,7 @@ enum fs_info_type none = 0, fat, ntfs, + refs, samba, nfs, netapp, @@ -98,6 +99,7 @@ class fs_info IMPLEMENT_STATUS_FLAG (bool, has_dos_filenames_only) IMPLEMENT_FS_FLAG (fat) IMPLEMENT_FS_FLAG (ntfs) + IMPLEMENT_FS_FLAG (refs) IMPLEMENT_FS_FLAG (samba) IMPLEMENT_FS_FLAG (nfs) IMPLEMENT_FS_FLAG (netapp) diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 7eee720aa..0e09cf41e 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -1252,7 +1252,11 @@ extern "C" PSECURITY_DESCRIPTOR, PULONG); VOID NTAPI RtlAcquirePebLock (); NTSTATUS NTAPI RtlAddAccessAllowedAce (PACL, ULONG, ACCESS_MASK, PSID); + NTSTATUS NTAPI RtlAddAccessAllowedAceEx (PACL, ULONG, ULONG, ACCESS_MASK, + PSID); NTSTATUS NTAPI RtlAddAccessDeniedAce (PACL, ULONG, ACCESS_MASK, PSID); + NTSTATUS NTAPI RtlAddAccessDeniedAceEx (PACL, ULONG, ULONG, ACCESS_MASK, + PSID); NTSTATUS NTAPI RtlAddAce (PACL, ULONG, ULONG, PVOID, ULONG); PVOID NTAPI RtlAllocateHeap (PVOID, ULONG, SIZE_T); NTSTATUS NTAPI RtlAppendUnicodeToString (PUNICODE_STRING, PCWSTR); diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index 3bbab4df7..ba229fe4b 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -347,6 +347,7 @@ class path_conv bool fs_got_fs () const { return fs.got_fs (); } bool fs_is_fat () const {return fs.is_fat ();} bool fs_is_ntfs () const {return fs.is_ntfs ();} + bool fs_is_refs () const {return fs.is_refs ();} bool fs_is_samba () const {return fs.is_samba ();} bool fs_is_nfs () const {return fs.is_nfs ();} bool fs_is_netapp () const {return fs.is_netapp ();} diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc index eee4886b1..d44705b2f 100644 --- a/winsup/cygwin/sec_helper.cc +++ b/winsup/cygwin/sec_helper.cc @@ -1,7 +1,7 @@ /* sec_helper.cc: NT security helper functions Copyright 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, - 2010, 2011 Red Hat, Inc. + 2010, 2011, 2012 Red Hat, Inc. Written by Corinna Vinschen <corinna@vinschen.de> @@ -578,6 +578,64 @@ __sec_user (PVOID sa_buf, PSID sid1, PSID sid2, DWORD access2, BOOL inherit) return psa; } +/* Helper function to create a file security descriptor which allows + full access to admins, system, and the sid given as parameter. See + try_to_bin for how it's used. */ + +PSECURITY_DESCRIPTOR +_recycler_sd (void *buf, bool users, bool dir) +{ + NTSTATUS status; + PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) buf; + + if (!psd) + return NULL; + RtlCreateSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION); + 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); + RtlAddAccessAllowedAceEx (dacl, ACL_REVISION, + dir ? CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE + : NO_INHERITANCE, + FILE_ALL_ACCESS, well_known_admins_sid); + RtlAddAccessAllowedAceEx (dacl, ACL_REVISION, + dir ? CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE + : NO_INHERITANCE, + FILE_ALL_ACCESS, well_known_system_sid); + if (users) + RtlAddAccessAllowedAceEx (dacl, ACL_REVISION, NO_PROPAGATE_INHERIT_ACE, + FILE_GENERIC_READ | FILE_GENERIC_EXECUTE + | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES, + well_known_users_sid); + else + RtlAddAccessAllowedAceEx (dacl, ACL_REVISION, + dir ? CONTAINER_INHERIT_ACE + | OBJECT_INHERIT_ACE + : NO_INHERITANCE, + FILE_ALL_ACCESS, cygheap->user.sid ()); + LPVOID ace; + status = RtlFirstFreeAce (dacl, &ace); + if (!NT_SUCCESS (status)) + { + debug_printf ("RtlFirstFreeAce: %p", status); + return NULL; + } + dacl->AclSize = (char *) ace - (char *) dacl; + RtlSetDaclSecurityDescriptor (psd, TRUE, dacl, FALSE); + /* If the directory DACL is not marked as protected, shell32 thinks + the recycle dir is corrupted. As soon as Explorer accesses the + Recycler, the user will get a GUI dialog "The Recycle Bin on X:\ + is corrupted. Do you want to empty the Recycle Bin for this drive?" + Of course we want to avoid that. */ + if (dir) + psd->Control |= SE_DACL_PROTECTED; + return psd; +} + /* Helper function to create an event security descriptor which only allows specific access to everyone. Only the creating process has all access rights. */ diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 3afd2b458..cf3888bd3 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -1,7 +1,7 @@ /* security.cc: NT file access control functions Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de Completely rewritten by Corinna Vinschen <corinna@vinschen.de> @@ -469,15 +469,13 @@ bool add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit) { - NTSTATUS status = RtlAddAccessAllowedAce (acl, ACL_REVISION, attributes, sid); + NTSTATUS status = RtlAddAccessAllowedAceEx (acl, ACL_REVISION, inherit, + attributes, sid); if (!NT_SUCCESS (status)) { __seterrno_from_nt_status (status); return false; } - ACCESS_ALLOWED_ACE *ace; - if (inherit && NT_SUCCESS (RtlGetAce (acl, offset, (PVOID *) &ace))) - ace->Header.AceFlags |= inherit; len_add += sizeof (ACCESS_ALLOWED_ACE) - sizeof (DWORD) + RtlLengthSid (sid); return true; } @@ -486,15 +484,13 @@ bool add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit) { - NTSTATUS status = RtlAddAccessDeniedAce (acl, ACL_REVISION, attributes, sid); + NTSTATUS status = RtlAddAccessDeniedAceEx (acl, ACL_REVISION, inherit, + attributes, sid); if (!NT_SUCCESS (status)) { __seterrno_from_nt_status (status); return false; } - ACCESS_DENIED_ACE *ace; - if (inherit && NT_SUCCESS (RtlGetAce (acl, offset, (PVOID *) &ace))) - ace->Header.AceFlags |= inherit; len_add += sizeof (ACCESS_DENIED_ACE) - sizeof (DWORD) + RtlLengthSid (sid); return true; } diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index 907cbe766..f80dcfbd7 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -476,6 +476,13 @@ extern SECURITY_ATTRIBUTES sec_none, sec_none_nih, sec_all, sec_all_nih; extern SECURITY_ATTRIBUTES *__stdcall __sec_user (PVOID, PSID, PSID, DWORD, BOOL) __attribute__ ((regparm (3))); + +extern PSECURITY_DESCRIPTOR _recycler_sd (void *buf, bool users, bool dir); +#define recycler_sd(users,dir) \ + (_recycler_sd (alloca (sizeof (SECURITY_DESCRIPTOR) + MAX_DACL_LEN (3)), \ + (users), \ + (dir))) + extern PSECURITY_DESCRIPTOR _everyone_sd (void *buf, ACCESS_MASK access); #define everyone_sd(access) (_everyone_sd (alloca (SD_MIN_SIZE), (access))) diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 9fc4a298c..657616ad9 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -200,7 +200,12 @@ stop_transaction (NTSTATUS status, HANDLE old_trans, HANDLE trans) } static char desktop_ini[] = - "[.ShellClassInfo]\r\nCLSID={645FF040-5081-101B-9F08-00AA002F954E}\r\n"; + "[.ShellClassInfo]\r\n" + "CLSID={645FF040-5081-101B-9F08-00AA002F954E}\r\n"; + +static char desktop_ini_ext[] = + "LocalizedResourceName=@%SystemRoot%\\system32\\shell32.dll,-8964\r\n"; + static BYTE info2[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -229,6 +234,7 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access) PFILE_INTERNAL_INFORMATION pfii; PFILE_RENAME_INFORMATION pfri; FILE_DISPOSITION_INFORMATION disp = { TRUE }; + bool fs_has_per_user_recycler = pc.fs_is_ntfs () || pc.fs_is_refs (); tmp_pathbuf tp; PBYTE infobuf = (PBYTE) tp.w_get (); @@ -253,8 +259,8 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access) RtlInitEmptyUnicodeString (&recycler, recyclerbuf, sizeof recyclerbuf); if (!pc.isremote ()) { - if (wincap.has_recycle_dot_bin ()) /* NTFS and FAT since Vista */ - RtlAppendUnicodeToString (&recycler, L"\\$Recycle.Bin\\"); + if (wincap.has_recycle_dot_bin ()) /* NTFS and FAT since Vista, ReFS */ + RtlAppendUnicodeToString (&recycler, L"\\$RECYCLE.BIN\\"); else if (pc.fs_is_ntfs ()) /* NTFS up to 2K3 */ RtlAppendUnicodeToString (&recycler, L"\\RECYCLER\\"); else if (pc.fs_is_fat ()) /* FAT up to 2K3 */ @@ -291,10 +297,10 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access) recycler.Length -= sizeof (WCHAR); /* Store length of recycler base dir, if it's necessary to create it. */ recycler_base_len = recycler.Length; - /* On NTFS the recycler dir contains user specific subdirs, which are the - actual recycle bins per user. The name if this dir is the string - representation of the user SID. */ - if (pc.fs_is_ntfs ()) + /* On NTFS or ReFS the recycler dir contains user specific subdirs, which + are the actual recycle bins per user. The name if this dir is the + string representation of the user SID. */ + if (fs_has_per_user_recycler) { UNICODE_STRING sid; WCHAR sidbuf[128]; @@ -344,6 +350,8 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access) /* Ok, so the recycler and/or the recycler/SID directory don't exist. First reopen root dir with permission to create subdirs. */ NtClose (rootdir); + InitializeObjectAttributes (&attr, &root, OBJ_CASE_INSENSITIVE, + NULL, NULL); status = NtOpenFile (&rootdir, FILE_ADD_SUBDIRECTORY, &attr, &io, FILE_SHARE_VALID_FLAGS, FILE_OPEN_FOR_BACKUP_INTENT); if (!NT_SUCCESS (status)) @@ -354,14 +362,17 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access) } /* Then check if recycler exists by opening and potentially creating it. Yes, we can really do that. Typically the recycle bin is created - by the first user actually using the bin. The permissions are the - default permissions propagated from the root directory. */ + by the first user actually using the bin. Pre-Vista, the permissions + are the default permissions propagated from the root directory. + Since Vista the top-level recycle dir has explicit permissions. */ InitializeObjectAttributes (&attr, &recycler, OBJ_CASE_INSENSITIVE, - rootdir, NULL); + rootdir, + wincap.has_recycle_dot_bin () + ? recycler_sd (true, true) : NULL); recycler.Length = recycler_base_len; status = NtCreateFile (&recyclerdir, READ_CONTROL - | (pc.fs_is_ntfs () ? 0 : FILE_ADD_FILE), + | (fs_has_per_user_recycler ? 0 : FILE_ADD_FILE), &attr, &io, NULL, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM @@ -376,10 +387,12 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access) } /* Next, if necessary, check if the recycler/SID dir exists and create it if not. */ - if (pc.fs_is_ntfs ()) + if (fs_has_per_user_recycler) { NtClose (recyclerdir); recycler.Length = recycler_user_len; + InitializeObjectAttributes (&attr, &recycler, OBJ_CASE_INSENSITIVE, + rootdir, recycler_sd (false, true)); status = NtCreateFile (&recyclerdir, READ_CONTROL | FILE_ADD_FILE, &attr, &io, NULL, FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_SYSTEM @@ -400,7 +413,7 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access) { RtlInitUnicodeString (&fname, L"desktop.ini"); InitializeObjectAttributes (&attr, &fname, OBJ_CASE_INSENSITIVE, - recyclerdir, NULL); + recyclerdir, recycler_sd (false, false)); status = NtCreateFile (&tmp_fh, FILE_GENERIC_WRITE, &attr, &io, NULL, FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN, FILE_SHARE_VALID_FLAGS, FILE_CREATE, @@ -416,6 +429,15 @@ try_to_bin (path_conv &pc, HANDLE &fh, ACCESS_MASK access) if (!NT_SUCCESS (status)) debug_printf ("NtWriteFile (%S) failed, status = %p", &fname, status); + else if (wincap.has_recycle_dot_bin ()) + { + status = NtWriteFile (tmp_fh, NULL, NULL, NULL, &io, + desktop_ini_ext, + sizeof desktop_ini_ext - 1, NULL, NULL); + if (!NT_SUCCESS (status)) + debug_printf ("NtWriteFile (%S) failed, status = %p", + &fname, status); + } NtClose (tmp_fh); } if (!wincap.has_recycle_dot_bin ()) /* No INFO2 file since Vista */ |