From c46d7be9a6cbbb16cd50038b30e818844793727d Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Thu, 27 Mar 2008 20:03:32 +0000 Subject: [PATCH] * flock.cc (FLOCK_PARENT_DIR_ACCESS): Define. (FLOCK_INODE_DIR_ACCESS): Define. (FLOCK_MUTANT_ACCESS): Define. (FLOCK_EVENT_ACCESS): Define. (SD_MIN_SIZE): Define. (everyone_sd): Define to simplify calling _everyone_sd. (_everyone_sd): Replace everyone_sync_sd. Take SECURITY_DESCRIPTOR as argument and allow to specify access mask. (get_lock_parent_dir): Open/Create parent dir with FLOCK_PARENT_DIR_ACCESS. Add text to api_fatal message. (inode_t::inode_t): Open/Create dir with FLOCK_INODE_DIR_ACCESS. Open/Create mutant with FLOCK_MUTANT_ACCESS. Add text to api_fatal message. (lockf_t::create_lock_obj): Create event with FLOCK_EVENT_ACCESS. Add text to api_fatal message. (lockf_t::open_lock_obj): Open event with FLOCK_EVENT_ACCESS. On failure, just return NULL pointer instead of calling api_fatal. (lockf_t::get_lock_obj_handle_count): Replace call to small_printf with call to debug_printf. (lf_setlock): Handle a failure to open the lock event object as EDEADLK. Call system_printf if opening sync objects fail. * ntdll.h (DIRECTORY_TRAVERSE): Define. (DIRECTORY_CREATE_OBJECT): Define. (DIRECTORY_CREATE_SUBDIRECTORY): Define. (EVENT_QUERY_STATE): Define. --- winsup/cygwin/ChangeLog | 28 +++++++++++++ winsup/cygwin/flock.cc | 93 ++++++++++++++++++++++++++++------------- winsup/cygwin/ntdll.h | 7 +++- 3 files changed, 97 insertions(+), 31 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index fe365db98..95f5d18cd 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,31 @@ +2008-03-27 Corinna Vinschen + + * flock.cc (FLOCK_PARENT_DIR_ACCESS): Define. + (FLOCK_INODE_DIR_ACCESS): Define. + (FLOCK_MUTANT_ACCESS): Define. + (FLOCK_EVENT_ACCESS): Define. + (SD_MIN_SIZE): Define. + (everyone_sd): Define to simplify calling _everyone_sd. + (_everyone_sd): Replace everyone_sync_sd. Take SECURITY_DESCRIPTOR as + argument and allow to specify access mask. + (get_lock_parent_dir): Open/Create parent dir with + FLOCK_PARENT_DIR_ACCESS. Add text to api_fatal message. + (inode_t::inode_t): Open/Create dir with FLOCK_INODE_DIR_ACCESS. + Open/Create mutant with FLOCK_MUTANT_ACCESS. Add text to api_fatal + message. + (lockf_t::create_lock_obj): Create event with FLOCK_EVENT_ACCESS. + Add text to api_fatal message. + (lockf_t::open_lock_obj): Open event with FLOCK_EVENT_ACCESS. + On failure, just return NULL pointer instead of calling api_fatal. + (lockf_t::get_lock_obj_handle_count): Replace call to small_printf + with call to debug_printf. + (lf_setlock): Handle a failure to open the lock event object as + EDEADLK. Call system_printf if opening sync objects fail. + * ntdll.h (DIRECTORY_TRAVERSE): Define. + (DIRECTORY_CREATE_OBJECT): Define. + (DIRECTORY_CREATE_SUBDIRECTORY): Define. + (EVENT_QUERY_STATE): Define. + 2008-03-27 Corinna Vinschen * syscalls.cc (rename): Fix setting errno in case of trailing "/." diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc index f33d317fb..64e2d22ea 100644 --- a/winsup/cygwin/flock.cc +++ b/winsup/cygwin/flock.cc @@ -216,23 +216,42 @@ allow_others_to_sync () } /* Helper function to create an event security descriptor which only allows - SYNCHRONIZE access to everyone. Only the creating process has all access + specific access to everyone. Only the creating process has all access rights. */ -static PSECURITY_DESCRIPTOR -everyone_sync_sd () -{ - static PSECURITY_DESCRIPTOR psd; - if (!psd) +#define FLOCK_PARENT_DIR_ACCESS (DIRECTORY_QUERY \ + | DIRECTORY_TRAVERSE \ + | DIRECTORY_CREATE_SUBDIRECTORY \ + | READ_CONTROL) + +#define FLOCK_INODE_DIR_ACCESS (DIRECTORY_QUERY \ + | DIRECTORY_TRAVERSE \ + | DIRECTORY_CREATE_OBJECT \ + | READ_CONTROL) + +#define FLOCK_MUTANT_ACCESS (MUTANT_QUERY_STATE \ + | SYNCHRONIZE \ + | READ_CONTROL) + +#define FLOCK_EVENT_ACCESS (EVENT_QUERY_STATE \ + | SYNCHRONIZE \ + | READ_CONTROL) + +#define SD_MIN_SIZE (sizeof (SECURITY_DESCRIPTOR) + MAX_DACL_LEN (1)) + +#define everyone_sd(access) (_everyone_sd (alloca (SD_MIN_SIZE), (access))) + +PSECURITY_DESCRIPTOR +_everyone_sd (void *buf, ACCESS_MASK access) +{ + PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) buf; + + if (psd) { - const size_t acl_len = sizeof (ACL) + - sizeof (ACCESS_ALLOWED_ACE) + MAX_SID_LEN; - psd = (PSECURITY_DESCRIPTOR) - malloc (sizeof (SECURITY_DESCRIPTOR) + acl_len); InitializeSecurityDescriptor (psd, SECURITY_DESCRIPTOR_REVISION); PACL dacl = (PACL) (psd + 1); - InitializeAcl (dacl, acl_len, ACL_REVISION); - if (!AddAccessAllowedAce (dacl, ACL_REVISION, SYNCHRONIZE, + InitializeAcl (dacl, MAX_DACL_LEN (1), ACL_REVISION); + if (!AddAccessAllowedAce (dacl, ACL_REVISION, access, well_known_world_sid)) { debug_printf ("AddAccessAllowedAce: %lu", GetLastError ()); @@ -265,13 +284,14 @@ get_lock_parent_dir () { RtlInitUnicodeString (&uname, L"\\BaseNamedObjects\\cygwin-fcntl-lk"); InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT, NULL, - sec_all.lpSecurityDescriptor); - status = NtOpenDirectoryObject (&dir, DIRECTORY_ALL_ACCESS, &attr); + everyone_sd (FLOCK_PARENT_DIR_ACCESS)); + status = NtOpenDirectoryObject (&dir, FLOCK_PARENT_DIR_ACCESS, &attr); if (!NT_SUCCESS (status)) { - status = NtCreateDirectoryObject (&dir, DIRECTORY_ALL_ACCESS, &attr); + status = NtCreateDirectoryObject (&dir, FLOCK_PARENT_DIR_ACCESS, + &attr); if (!NT_SUCCESS (status)) - api_fatal ("NtCreateDirectoryObject: %p", status); + api_fatal ("NtCreateDirectoryObject(parent): %p", status); } } INODE_LIST_UNLOCK (); @@ -446,25 +466,25 @@ inode_t::inode_t (dev_t dev, ino_t ino) int len = __small_swprintf (name, L"%08x-%016X", dev, ino); RtlInitCountedUnicodeString (&uname, name, len * sizeof (WCHAR)); InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT, parent_dir, - sec_all.lpSecurityDescriptor); - status = NtOpenDirectoryObject (&i_dir, DIRECTORY_ALL_ACCESS, &attr); + everyone_sd (FLOCK_INODE_DIR_ACCESS)); + status = NtOpenDirectoryObject (&i_dir, FLOCK_INODE_DIR_ACCESS, &attr); if (!NT_SUCCESS (status)) { - status = NtCreateDirectoryObject (&i_dir, DIRECTORY_ALL_ACCESS, &attr); + status = NtCreateDirectoryObject (&i_dir, FLOCK_INODE_DIR_ACCESS, &attr); if (!NT_SUCCESS (status)) - api_fatal ("NtCreateDirectoryObject: %p", status); + api_fatal ("NtCreateDirectoryObject(inode): %p", status); } /* Create a mutex object in the file specific dir, which is used for access synchronization on the dir and its objects. */ RtlInitUnicodeString (&uname, L"mtx"); InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT, i_dir, - sec_all.lpSecurityDescriptor); - status = NtOpenMutant (&i_mtx, MUTANT_ALL_ACCESS, &attr); + everyone_sd (FLOCK_MUTANT_ACCESS)); + status = NtOpenMutant (&i_mtx, FLOCK_MUTANT_ACCESS, &attr); if (!NT_SUCCESS (status)) { - status = NtCreateMutant (&i_mtx, MUTANT_ALL_ACCESS, &attr, FALSE); + status = NtCreateMutant (&i_mtx, FLOCK_MUTANT_ACCESS, &attr, FALSE); if (!NT_SUCCESS (status)) - api_fatal ("NtCreateMutant: %p", status); + api_fatal ("NtCreateMutant(inode): %p", status); } } @@ -553,11 +573,11 @@ lockf_t::create_lock_obj () RtlInitCountedUnicodeString (&uname, name, LOCK_OBJ_NAME_LEN * sizeof (WCHAR)); InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT, lf_inode->i_dir, - everyone_sync_sd ()); + everyone_sd (FLOCK_EVENT_ACCESS)); status = NtCreateEvent (&lf_obj, EVENT_ALL_ACCESS, &attr, NotificationEvent, FALSE); if (!NT_SUCCESS (status)) - api_fatal ("NtCreateEvent: %p", status); + api_fatal ("NtCreateEvent(lock): %p", status); } /* Open a lock event object for SYNCHRONIZE access (to wait for it). */ @@ -577,9 +597,12 @@ lockf_t::open_lock_obj () const LOCK_OBJ_NAME_LEN * sizeof (WCHAR)); InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT, lf_inode->i_dir, NULL); - status = NtOpenEvent (&obj, SYNCHRONIZE, &attr); + status = NtOpenEvent (&obj, FLOCK_EVENT_ACCESS, &attr); if (!NT_SUCCESS (status)) - api_fatal ("NtOpenEvent: %p", status); + { + SetLastError (RtlNtStatusToDosError (status)); + return NULL; + } return obj; } @@ -596,7 +619,7 @@ lockf_t::get_lock_obj_handle_count () const status = NtQueryObject (lf_obj, ObjectBasicInformation, &obi, sizeof obi, NULL); if (!NT_SUCCESS (status)) - small_printf ("NtQueryObject: %p\n", status); + debug_printf ("NtQueryObject: %p\n", status); else hdl_cnt = obi.HandleCount; } @@ -892,13 +915,23 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean) /* Wait for the blocking object and its holding process. */ HANDLE obj = block->open_lock_obj (); + if (!obj) + { + /* We can't synchronize on the lock event object. + Treat this as a deadlock-like situation for now. */ + system_printf ("Can't sync with lock object hold by " + "Win32 pid %lu: %E", block->lf_wid); + NtClose (obj); + return EDEADLK; + } HANDLE proc = OpenProcess (SYNCHRONIZE, FALSE, block->lf_wid); if (!proc) { /* If we can't synchronize on the process holding the lock, we will never recognize when the lock has been abandoned. Treat this as a deadlock-like situation for now. */ - debug_printf ("OpenProcess: %E"); + system_printf ("Can't sync with process holding a lock " + "(Win32 pid %lu): %E", block->lf_wid); NtClose (obj); return EDEADLK; } diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h index 695c229cd..7ccd2e5bd 100644 --- a/winsup/cygwin/ntdll.h +++ b/winsup/cygwin/ntdll.h @@ -1,6 +1,6 @@ /* ntdll.h. Contains ntdll specific stuff not defined elsewhere. - Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc. + Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc. This file is part of Cygwin. @@ -189,8 +189,13 @@ typedef struct _FILE_ID_BOTH_DIR_INFORMATION #define LOCK_VM_IN_RAM 2 #define DIRECTORY_QUERY 1 +#define DIRECTORY_TRAVERSE 2 +#define DIRECTORY_CREATE_OBJECT 4 +#define DIRECTORY_CREATE_SUBDIRECTORY 8 #define DIRECTORY_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED|0x0f) +#define EVENT_QUERY_STATE 1 + typedef ULONG KAFFINITY; typedef enum _SYSTEM_INFORMATION_CLASS