summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/ChangeLog28
-rw-r--r--winsup/cygwin/globals.cc1
-rw-r--r--winsup/cygwin/mount.cc1
-rw-r--r--winsup/cygwin/mount.h2
-rw-r--r--winsup/cygwin/ntdll.h4
-rw-r--r--winsup/cygwin/path.h1
-rw-r--r--winsup/cygwin/sec_helper.cc60
-rw-r--r--winsup/cygwin/security.cc14
-rw-r--r--winsup/cygwin/security.h7
-rw-r--r--winsup/cygwin/syscalls.cc48
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 */