diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b271707e5..834fe7ac0 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,34 @@ +2012-02-14 Corinna Vinschen + + * cygheap.cc (init_cygheap::init_installation_root): Convert function + init_installation_root into a cygheap method. + * cygheap.h (struct init_cygheap): Move installation_root, + installation_key, and installation_key_buf from shared + .cygwin_dll_common DLL section to cygheap. Declare new method + init_installation_root. + * dtable.cc (handle_to_fn): Accommodate the move of installation strings + to the cygheap. + * external.cc (cygwin_internal): Ditto. + * fhandler_console.cc (fhandler_console::open_shared_console): Ditto. + * fhandler_mailslot.cc (fhandler_mailslot::get_object_attr): Ditto. + * fhandler_tty.cc: Ditto, throughout. + * mount.cc (mount_info::init): Ditto. + * pipe.cc (fhandler_pipe::create): Ditto. + * shared.cc: Ditto, throughout. + (installation_root): Remove. + (installation_key): Move to cygheap. + (installation_key_buf): Ditto. + (installation_root_inited): Remove. + (SPIN_WAIT): Remove. + (init_installation_root): Move to cygheap. + (memory_init): Call cygheap->init_installation_root right after + cygheap->user.init. Drop call of init_installation_root function. + * shared_info.h (init_installation_root): Drop declaration. + (installation_root): Ditto. + (installation_key): Ditto. + * uinfo.cc (pwdgrp::load): Accommodate the move of installation strings + to the cygheap. + 2012-02-14 Corinna Vinschen * thread.cc: Drop including unused headers. diff --git a/winsup/cygwin/cygheap.cc b/winsup/cygwin/cygheap.cc index 31212666d..bc96a5533 100644 --- a/winsup/cygwin/cygheap.cc +++ b/winsup/cygwin/cygheap.cc @@ -23,6 +23,8 @@ #include "heap.h" #include "sigproc.h" #include "pinfo.h" +#include "registry.h" +#include "ntdll.h" #include #include @@ -138,6 +140,84 @@ _csbrk (int sbs) return prebrk; } +/* Use absolute path of cygwin1.dll to derive the Win32 dir which + is our installation_root. Note that we can't handle Cygwin installation + root dirs of more than 4K path length. I assume that's ok... + + This function also generates the installation_key value. It's a 64 bit + hash value based on the path of the Cygwin DLL itself. It's subsequently + used when generating shared object names. Thus, different Cygwin + installations generate different object names and so are isolated from + each other. + + Having this information, the installation key together with the + installation root path is written to the registry. The idea is that + cygcheck can print the paths into which the Cygwin DLL has been + installed for debugging purposes. + + Last but not least, the new cygwin properties datastrcuture is checked + for the "disabled_key" value, which is used to determine whether the + installation key is actually added to all object names or not. This is + used as a last resort for debugging purposes, usually. However, there + could be another good reason to re-enable object name collisions between + multiple Cygwin DLLs, which we're just not aware of right now. Cygcheck + can be used to change the value in an existing Cygwin DLL binary. */ +void +init_cygheap::init_installation_root () +{ + if (!GetModuleFileNameW (cygwin_hmodule, installation_root, PATH_MAX)) + api_fatal ("Can't initialize Cygwin installation root dir.\n" + "GetModuleFileNameW(%p, %p, %u), %E", + cygwin_hmodule, installation_root, PATH_MAX); + PWCHAR p = installation_root; + if (wcsncmp (p, L"\\\\?\\", 4)) /* No long path prefix. */ + { + if (!wcsncasecmp (p, L"\\\\", 2)) /* UNC */ + { + p = wcpcpy (p, L"\\??\\UN"); + GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 6); + *p = L'C'; + } + else + { + p = wcpcpy (p, L"\\??\\"); + GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 4); + } + } + installation_root[1] = L'?'; + + RtlInitEmptyUnicodeString (&installation_key, installation_key_buf, + sizeof installation_key_buf); + RtlInt64ToHexUnicodeString (hash_path_name (0, installation_root), + &installation_key, FALSE); + + PWCHAR w = wcsrchr (installation_root, L'\\'); + if (w) + { + *w = L'\0'; + w = wcsrchr (installation_root, L'\\'); + } + if (!w) + api_fatal ("Can't initialize Cygwin installation root dir.\n" + "Invalid DLL path"); + *w = L'\0'; + + for (int i = 1; i >= 0; --i) + { + reg_key r (i, KEY_WRITE, _WIDE (CYGWIN_INFO_INSTALLATIONS_NAME), + NULL); + if (NT_SUCCESS (r.set_string (installation_key_buf, + installation_root))) + break; + } + + if (cygwin_props.disable_key) + { + installation_key.Length = 0; + installation_key.Buffer[0] = L'\0'; + } +} + void __stdcall cygheap_init () { diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index 7c2380e4d..054297bd7 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -280,6 +280,9 @@ struct init_cygheap: public mini_cygheap { _cmalloc_entry *chain; char *buckets[32]; + WCHAR installation_root[PATH_MAX]; + UNICODE_STRING installation_key; + WCHAR installation_key_buf[18]; cygheap_root root; cygheap_user user; user_heap_info user_heap; @@ -303,6 +306,7 @@ struct init_cygheap: public mini_cygheap } inode_list; /* Global inode pointer for adv. locking. */ hook_chain hooks; void close_ctty (); + void init_installation_root (); }; diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc index fa442f771..f152b82a3 100644 --- a/winsup/cygwin/dtable.cc +++ b/winsup/cygwin/dtable.cc @@ -931,8 +931,9 @@ handle_to_fn (HANDLE h, char *posix_fn) return false; w32 += WCLEN (L"cygwin-"); /* Check for installation key and trailing dash. */ - w32len = installation_key.Length / sizeof (WCHAR); - if (w32len && wcsncmp (w32, installation_key.Buffer, w32len) != 0) + w32len = cygheap->installation_key.Length / sizeof (WCHAR); + if (w32len + && wcsncmp (w32, cygheap->installation_key.Buffer, w32len) != 0) return false; w32 += w32len; if (*w32 != L'-') diff --git a/winsup/cygwin/external.cc b/winsup/cygwin/external.cc index e6e349395..146dda953 100644 --- a/winsup/cygwin/external.cc +++ b/winsup/cygwin/external.cc @@ -1,7 +1,7 @@ /* external.cc: Interface to Cygwin internals from external programs. 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. Written by Christopher Faylor @@ -468,9 +468,8 @@ cygwin_internal (cygwin_getinfo_types t, ...) break; case CW_GET_INSTKEY: { - extern WCHAR installation_key_buf[18]; PWCHAR dest = va_arg (arg, PWCHAR); - wcscpy (dest, installation_key_buf); + wcscpy (dest, cygheap->installation_key_buf); res = 0; } break; diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 134b26141..01892f69e 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -82,7 +82,7 @@ fhandler_console::console_state * fhandler_console::open_shared_console (HWND hw, HANDLE& h, bool& create) { wchar_t namebuf[(sizeof "XXXXXXXXXXXXXXXXXX-consNNNNNNNNNN")]; - __small_swprintf (namebuf, L"%S-cons%p", &installation_key, hw); + __small_swprintf (namebuf, L"%S-cons%p", &cygheap->installation_key, hw); shared_locations m = create ? SH_SHARED_CONSOLE : SH_JUSTOPEN; console_state *res = (console_state *) diff --git a/winsup/cygwin/fhandler_mailslot.cc b/winsup/cygwin/fhandler_mailslot.cc index 7e4052137..52526356a 100644 --- a/winsup/cygwin/fhandler_mailslot.cc +++ b/winsup/cygwin/fhandler_mailslot.cc @@ -1,6 +1,6 @@ /* fhandler_mailslot.cc. See fhandler.h for a description of the fhandler classes. - Copyright 2005, 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. + Copyright 2005, 2007, 2008, 2009, 2010, 2011, 2012 Red Hat, Inc. This file is part of Cygwin. @@ -11,8 +11,11 @@ #include "winsup.h" #include "cygerrno.h" +#include "security.h" #include "path.h" #include "fhandler.h" +#include "dtable.h" +#include "cygheap.h" #include "ntdll.h" #include "shared_info.h" #include "tls_pbuf.h" @@ -51,7 +54,7 @@ fhandler_mailslot::get_object_attr (OBJECT_ATTRIBUTES &attr, { RtlCopyUnicodeString (path, pc.get_nt_native_path ()); - RtlAppendUnicodeStringToString (path, &installation_key); + RtlAppendUnicodeStringToString (path, &cygheap->installation_key); InitializeObjectAttributes (&attr, path, OBJ_CASE_INSENSITIVE | (flags & O_CLOEXEC ? 0 : OBJ_INHERIT), diff --git a/winsup/cygwin/fhandler_tty.cc b/winsup/cygwin/fhandler_tty.cc index 064dc41dc..b316a0aaf 100644 --- a/winsup/cygwin/fhandler_tty.cc +++ b/winsup/cygwin/fhandler_tty.cc @@ -488,7 +488,7 @@ fhandler_pty_slave::open (int flags, mode_t) DWORD len; __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl", - &installation_key, get_unit ()); + &cygheap->installation_key, get_unit ()); termios_printf ("dup handles via master control pipe %s", buf); if (!CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl, &len, 500)) @@ -1272,7 +1272,7 @@ fhandler_pty_master::close () DWORD len; __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl", - &installation_key, get_unit ()); + &cygheap->installation_key, get_unit ()); CallNamedPipe (buf, &req, sizeof req, &repl, sizeof repl, &len, 500); CloseHandle (master_ctl); master_thread->detach (); @@ -1675,7 +1675,7 @@ fhandler_pty_master::setup () /* Create master control pipe which allows the master to duplicate the pty pipe handles to processes which deserve it. */ __small_sprintf (buf, "\\\\.\\pipe\\cygwin-%S-pty%d-master-ctl", - &installation_key, unit); + &cygheap->installation_key, unit); master_ctl = CreateNamedPipe (buf, PIPE_ACCESS_DUPLEX, PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 4096, 4096, diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc index 5724298b3..ef7d746df 100644 --- a/winsup/cygwin/mount.cc +++ b/winsup/cygwin/mount.cc @@ -467,7 +467,7 @@ mount_info::init () PWCHAR pathend; WCHAR path[PATH_MAX]; - pathend = wcpcpy (path, installation_root); + pathend = wcpcpy (path, cygheap->installation_root); create_root_entry (path); pathend = wcpcpy (pathend, L"\\etc\\fstab"); diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc index 6befd2222..52f2ba058 100644 --- a/winsup/cygwin/pipe.cc +++ b/winsup/cygwin/pipe.cc @@ -1,7 +1,7 @@ /* pipe.cc: pipe for Cygwin. Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011, 2011 Hat, Inc. + 2008, 2009, 2010, 2011, 2012 Hat, Inc. This file is part of Cygwin. @@ -212,7 +212,7 @@ fhandler_pipe::create (LPSECURITY_ATTRIBUTES sa_ptr, PHANDLE r, PHANDLE w, char pipename[MAX_PATH]; const size_t len = __small_sprintf (pipename, PIPE_INTRO "%S-", - &installation_key); + &cygheap->installation_key); if (name) strcpy (pipename + len, name); diff --git a/winsup/cygwin/shared.cc b/winsup/cygwin/shared.cc index e9f461338..86f93c269 100644 --- a/winsup/cygwin/shared.cc +++ b/winsup/cygwin/shared.cc @@ -1,7 +1,7 @@ /* shared.cc: shared data area support. Copyright 1996, 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. This file is part of Cygwin. @@ -34,96 +34,6 @@ user_info NO_COPY *user_shared; HANDLE NO_COPY cygwin_shared_h; HANDLE NO_COPY cygwin_user_h; -WCHAR installation_root[PATH_MAX] __attribute__((section (".cygwin_dll_common"), shared)); -UNICODE_STRING installation_key __attribute__((section (".cygwin_dll_common"), shared)); -WCHAR installation_key_buf[18] __attribute__((section (".cygwin_dll_common"), shared)); -static LONG installation_root_inited __attribute__((section (".cygwin_dll_common"), shared)); - -#define SPIN_WAIT 10000 - -/* Use absolute path of cygwin1.dll to derive the Win32 dir which - is our installation_root. Note that we can't handle Cygwin installation - root dirs of more than 4K path length. I assume that's ok... - - This function also generates the installation_key value. It's a 64 bit - hash value based on the path of the Cygwin DLL itself. It's subsequently - used when generating shared object names. Thus, different Cygwin - installations generate different object names and so are isolated from - each other. - - Having this information, the installation key together with the - installation root path is written to the registry. The idea is that - cygcheck can print the paths into which the Cygwin DLL has been - installed for debugging purposes. - - Last but not least, the new cygwin properties datastrcuture is checked - for the "disabled_key" value, which is used to determine whether the - installation key is actually added to all object names or not. This is - used as a last resort for debugging purposes, usually. However, there - could be another good reason to re-enable object name collisions between - multiple Cygwin DLLs, which we're just not aware of right now. Cygcheck - can be used to change the value in an existing Cygwin DLL binary. */ - -void inline -init_installation_root () -{ - spinlock iri (installation_root_inited); - if (!iri) - { - if (!GetModuleFileNameW (cygwin_hmodule, installation_root, PATH_MAX)) - api_fatal ("Can't initialize Cygwin installation root dir.\n" - "GetModuleFileNameW(%p, %p, %u), %E", - cygwin_hmodule, installation_root, PATH_MAX); - PWCHAR p = installation_root; - if (wcsncmp (p, L"\\\\?\\", 4)) /* No long path prefix. */ - { - if (!wcsncasecmp (p, L"\\\\", 2)) /* UNC */ - { - p = wcpcpy (p, L"\\??\\UN"); - GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 6); - *p = L'C'; - } - else - { - p = wcpcpy (p, L"\\??\\"); - GetModuleFileNameW (cygwin_hmodule, p, PATH_MAX - 4); - } - } - installation_root[1] = L'?'; - - RtlInitEmptyUnicodeString (&installation_key, installation_key_buf, - sizeof installation_key_buf); - RtlInt64ToHexUnicodeString (hash_path_name (0, installation_root), - &installation_key, FALSE); - - PWCHAR w = wcsrchr (installation_root, L'\\'); - if (w) - { - *w = L'\0'; - w = wcsrchr (installation_root, L'\\'); - } - if (!w) - api_fatal ("Can't initialize Cygwin installation root dir.\n" - "Invalid DLL path"); - *w = L'\0'; - - for (int i = 1; i >= 0; --i) - { - reg_key r (i, KEY_WRITE, _WIDE (CYGWIN_INFO_INSTALLATIONS_NAME), - NULL); - if (NT_SUCCESS (r.set_string (installation_key_buf, - installation_root))) - break; - } - - if (cygwin_props.disable_key) - { - installation_key.Length = 0; - installation_key.Buffer[0] = L'\0'; - } - } -} - /* This function returns a handle to the top-level directory in the global NT namespace used to implement global objects including shared memory. */ @@ -142,7 +52,7 @@ get_shared_parent_dir () __small_swprintf (bnoname, L"\\BaseNamedObjects\\%s%s-%S", cygwin_version.shared_id, _cygwin_testing ? cygwin_version.dll_build_date : "", - &installation_key); + &cygheap->installation_key); RtlInitUnicodeString (&uname, bnoname); InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF, NULL, everyone_sd (CYG_SHARED_DIR_ACCESS)); @@ -178,7 +88,7 @@ get_session_parent_dir () L"\\Sessions\\BNOLINKS\\%d\\%s%s-%S", psi.SessionId, cygwin_version.shared_id, _cygwin_testing ? cygwin_version.dll_build_date : "", - &installation_key); + &cygheap->installation_key); RtlInitUnicodeString (&uname, bnoname); InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF, NULL, everyone_sd(CYG_SHARED_DIR_ACCESS)); @@ -422,7 +332,7 @@ shared_info::initialize () up to this point. Debug output except for system_printf requires the global shared memory to exist. */ debug_printf ("Installation root: <%W> key: <%S>", - installation_root, &installation_key); + cygheap->installation_root, &cygheap->installation_key); } else if (sversion != (LONG) CURR_SHARED_MAGIC) sversion.multiple_cygwin_problem ("system shared memory version", @@ -441,9 +351,9 @@ memory_init (bool init_cygheap) { cygheap_init (); cygheap->user.init (); + cygheap->init_installation_root (); /* Requires user.init! */ } - init_installation_root (); /* Initialize installation root dir */ shared_info::create (); /* Initialize global shared memory */ user_info::create (false); /* Initialize per-user shared memory */ } diff --git a/winsup/cygwin/shared_info.h b/winsup/cygwin/shared_info.h index e6f9c832e..a569ea5ba 100644 --- a/winsup/cygwin/shared_info.h +++ b/winsup/cygwin/shared_info.h @@ -1,7 +1,7 @@ /* shared_info.h: shared info for cygwin Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, - 2010, 2011 Red Hat, Inc. + 2010, 2011, 2012 Red Hat, Inc. This file is part of Cygwin. @@ -93,6 +93,3 @@ void *__stdcall open_shared (const WCHAR *, int, HANDLE&, DWORD, shared_locations *, PSECURITY_ATTRIBUTES = &sec_all, DWORD = FILE_MAP_READ | FILE_MAP_WRITE); extern void user_shared_create (bool reinit); -extern void init_installation_root (); -extern WCHAR installation_root[PATH_MAX]; -extern UNICODE_STRING installation_key; diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc index e0f6e910d..a26ccb88e 100644 --- a/winsup/cygwin/uinfo.cc +++ b/winsup/cygwin/uinfo.cc @@ -549,13 +549,13 @@ pwdgrp::load (const wchar_t *rel_path) curr_lines = 0; if (!path && - !(path = (PWCHAR) malloc ((wcslen (installation_root) + !(path = (PWCHAR) malloc ((wcslen (cygheap->installation_root) + wcslen (rel_path) + 1) * sizeof (WCHAR)))) { paranoid_printf ("malloc (%W) failed", rel_path); goto out; } - wcpcpy (wcpcpy (path, installation_root), rel_path); + wcpcpy (wcpcpy (path, cygheap->installation_root), rel_path); RtlInitUnicodeString (&upath, path); InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);