+2009-10-31 Corinna Vinschen <corinna@vinschen.de>
+
+ * cygprops.h: New file.
+ * dtable.cc (handle_to_fn): Add check for correct installation_key
+ string in object name for pipes and ttys.
+ * external.cc (cygwin_internal): Add CW_GET_INSTKEY to allow fetching
+ the installation_key from cygserver.
+ * fhandler_fifo.cc (fhandler_fifo::fifo_name): Add installation_key
+ to fifo name.
+ * globals.cc: Include cygprops.h.
+ (_RDATA): Move slightly and add comment.
+ (cygwin_props): Define.
+ * mount.cc (mount_info::init): Accommodate the fact that
+ installation_root is now a global variable in DLL common shared memory,
+ rather than a member of cygwin_shared.
+ * pipe.cc (fhandler_pipe::create_selectable): Add installation_key to
+ pipe name.
+ * shared.cc (installation_root): Define here for storage in DLL
+ common shared memory.
+ (installation_key): Ditto.
+ (installation_key_buf): Ditto.
+ (init_installation_root): Convert from shared_info method to ordinary
+ function. Add initializing installation_key. Invalidate
+ installation_key depending of value of disable_key property. Add
+ comment to explain.
+ (get_shared_parent_dir): Add installation_key to directory name.
+ (get_session_parent_dir): Ditto.
+ (shared_info::initialize): Move call to init_installation_root from
+ here...
+ (memory_init): ...to here. Add debug output to print installation root
+ and installation key. Add comment to explain why.
+ * shared_info.h (SHARED_INFO_CB): Recalculate.
+ (CURR_SHARED_MAGIC): Ditto.
+ (class shared_info): Remove definition of installation_root and
+ declaration of init_installation_root.
+ (init_installation_root): Declare.
+ (installation_root): Declare.
+ (installation_key): Declare.
+ * uinfo.cc (pwdgrp::load): Accommodate the fact that installation_root
+ is now a global variable in DLL common shared memory.
+ * include/cygwin/version.h: Bump API minor number.
+ (CYGWIN_INFO_INSTALLATIONS_NAME): Add.
+ * include/sys/cygwin.h (cygwin_getinfo_types): Add CW_GET_INSTKEY.
+
2009-10-31 Corinna Vinschen <corinna@vinschen.de>
* sec_helper.cc (security_descriptor::realloc): Call free first if
--- /dev/null
+/* cygprops.h: Cygwin DLL properties
+
+ Copyright 2009 Red Hat, Inc.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+/* DLL properties data. */
+struct cygwin_props_t
+{
+ char magic[68];
+ ULONG size;
+ ULONG disable_key;
+};
+
+#define CYGWIN_PROPS_MAGIC \
+ "Fortunately, I keep my feathers numbered for just such an emergency"
if (wcsncmp (w32, L"cygwin-", WCLEN (L"cygwin-")) != 0)
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)
+ return false;
+ w32 += w32len;
+ if (*w32 != L'-')
+ return false;
+ ++w32;
bool istty = wcsncmp (w32, L"tty", WCLEN (L"tty")) == 0;
if (istty)
decode_tty (posix_fn, w32 + WCLEN (L"tty"));
res = 0;
}
break;
+ case CW_GET_INSTKEY:
+ {
+ extern WCHAR installation_key_buf[18];
+ PWCHAR dest = va_arg (arg, PWCHAR);
+ wcscpy (dest, installation_key_buf);
+ res = 0;
+ }
+ break;
default:
set_errno (ENOSYS);
#include "cygheap.h"
#include "sigproc.h"
#include "cygtls.h"
+#include "shared_info.h"
fhandler_fifo::fhandler_fifo ():
wait_state (fifo_unknown), dummy_client (NULL)
fhandler_fifo::fifo_name (char *buf)
{
/* Generate a semi-unique name to associate with this fifo. */
- __small_sprintf (buf, "\\\\.\\pipe\\__cygfifo__%08x_%016X",
- get_dev (), get_ino ());
+ __small_sprintf (buf, "\\\\.\\pipe\\__cygfifo__%S_%08x_%016X",
+ &installation_key, get_dev (), get_ino ());
return buf;
}
#include "winsup.h"
#include "cygtls.h"
#include "perprocess.h"
+#include "cygprops.h"
#include "thread.h"
#include <malloc.h>
#include <cygwin/version.h>
char *old_title;
+/* Define globally used, but readonly variables using the _RDATA attribute. */
+#define _RDATA __attribute__ ((section(".rdata")))
+
/* Heavily-used const UNICODE_STRINGs are defined here once. The idea is a
speed improvement by not having to initialize a UNICODE_STRING every time
we make a string comparison. The strings are not defined as const,
{ Length: sizeof (_s) - sizeof (WCHAR), \
MaximumLength: sizeof (_s), \
Buffer: (PWSTR) (_s) }
-#define _RDATA __attribute__ ((section(".rdata")))
UNICODE_STRING _RDATA ro_u_empty = _ROU (L"");
UNICODE_STRING _RDATA ro_u_lnk = _ROU (L".lnk");
UNICODE_STRING _RDATA ro_u_exe = _ROU (L".exe");
UNICODE_STRING _RDATA ro_u_udf = _ROU (L"UDF");
UNICODE_STRING _RDATA ro_u_unixfs = _ROU (L"UNIXFS");
UNICODE_STRING _RDATA ro_u_volume = _ROU (L"\\??\\Volume{");
-#undef _RDATA
#undef _ROU
+/* Cygwin properties are meant to be readonly data placed in the DLL, but
+ which can be changed by external tools to make adjustments to the
+ behaviour of a DLL based on the binary of the DLL itself. This is
+ different from $CYGWIN since it only affects that very DLL, not all
+ DLLs which have access to the $CYGWIN environment variable. */
+cygwin_props_t _RDATA cygwin_props =
+{
+ CYGWIN_PROPS_MAGIC,
+ sizeof (cygwin_props_t),
+ 0
+};
+
+#undef _RDATA
+
extern "C"
{
/* This is an exported copy of environ which can be used by DLLs
214: Export execvpe, fexecve.
215: CW_EXIT_PROCESS added.
216: CW_SET_EXTERNAL_TOKEN added.
+ 217: CW_GET_INSTKEY added.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 216
+#define CYGWIN_VERSION_API_MINOR 217
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
#define CYGWIN_INFO_CYGWIN_REGISTRY_NAME "Cygwin"
#define CYGWIN_INFO_PROGRAM_OPTIONS_NAME "Program Options"
+#define CYGWIN_INFO_INSTALLATIONS_NAME "Installations"
/* The default cygdrive prefix. */
CW_SET_PRIV_KEY,
CW_SETERRNO,
CW_EXIT_PROCESS,
- CW_SET_EXTERNAL_TOKEN
+ CW_SET_EXTERNAL_TOKEN,
+ CW_GET_INSTKEY
} cygwin_getinfo_types;
/* Token type for CW_SET_EXTERNAL_TOKEN */
PWCHAR pathend;
WCHAR path[PATH_MAX];
- pathend = wcpcpy (path, cygwin_shared->installation_root);
+ pathend = wcpcpy (path, installation_root);
create_root_entry (path);
pathend = wcpcpy (pathend, L"\\etc\\fstab");
#include "dtable.h"
#include "cygheap.h"
#include "pinfo.h"
+#include "shared_info.h"
fhandler_pipe::fhandler_pipe ()
: fhandler_base (), popen_pid (0), overlapped (NULL)
if (psize < PIPE_BUF)
psize = PIPE_BUF;
- char pipename[MAX_PATH] = PIPE_INTRO;
+ char pipename[MAX_PATH];
+ const size_t len = __small_sprintf (pipename, PIPE_INTRO "%S-",
+ &installation_key);
+
/* FIXME: Eventually make ttys work with overlapped I/O. */
DWORD overlapped = name ? 0 : FILE_FLAG_OVERLAPPED;
{
static volatile ULONG pipe_unique_id;
if (!name)
- __small_sprintf (pipename + strlen(PIPE_INTRO), "pipe-%p-%p", myself->pid,
+ __small_sprintf (pipename + len, "pipe-%p-%p", myself->pid,
InterlockedIncrement ((LONG *) &pipe_unique_id));
else
- strcpy (pipename + strlen(PIPE_INTRO), name);
+ strcpy (pipename + len, name);
debug_printf ("CreateNamedPipe: name %s, size %lu", pipename, psize);
#include "ntdll.h"
#include <alloca.h>
#include <wchar.h>
+#include <wingdi.h>
+#include <winuser.h>
shared_info NO_COPY *cygwin_shared;
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));
+
+/* 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_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, CYGWIN_INFO_INSTALLATIONS_NAME, NULL);
+ if (r.set_string (installation_key_buf, installation_root)
+ == ERROR_SUCCESS)
+ 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. */
if (!dir)
{
WCHAR bnoname[MAX_PATH];
- __small_swprintf (bnoname, L"\\BaseNamedObjects\\%s%s",
+ __small_swprintf (bnoname, L"\\BaseNamedObjects\\%s%s-%S",
cygwin_version.shared_id,
- _cygwin_testing ? cygwin_version.dll_build_date : "");
+ _cygwin_testing ? cygwin_version.dll_build_date : "",
+ &installation_key);
RtlInitUnicodeString (&uname, bnoname);
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
NULL, everyone_sd (CYG_SHARED_DIR_ACCESS));
{
WCHAR bnoname[MAX_PATH];
__small_swprintf (bnoname,
- L"\\Sessions\\BNOLINKS\\%d\\%s%s",
+ L"\\Sessions\\BNOLINKS\\%d\\%s%s-%S",
psi.SessionId, cygwin_version.shared_id,
- _cygwin_testing ? cygwin_version.dll_build_date : "");
+ _cygwin_testing ? cygwin_version.dll_build_date : "",
+ &installation_key);
RtlInitUnicodeString (&uname, bnoname);
InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF,
NULL, everyone_sd(CYG_SHARED_DIR_ACCESS));
UnmapViewOfFile (user_shared);
}
-/* 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... */
-void
-shared_info::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'?';
-
- 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';
-}
-
/* Initialize obcaseinsensitive. Default to case insensitive on pre-XP. */
void
shared_info::init_obcaseinsensitive ()
if (!sversion)
{
- init_installation_root ();/* Initialize installation root dir. */
init_obcaseinsensitive ();/* Initialize obcaseinsensitive. */
tty.init (); /* Initialize tty table. */
mt.initialize (); /* Initialize shared tape information. */
cygheap->user.init ();
}
+ /* Initialize installation root dir. */
+ if (!installation_root[0])
+ init_installation_root ();
+
/* Initialize general shared memory */
shared_locations sh_cygwin_shared;
cygwin_shared = (shared_info *) open_shared (L"shared",
cygwin_shared_h,
sizeof (*cygwin_shared),
sh_cygwin_shared = SH_CYGWIN_SHARED);
+ /* Defer debug output printing the installation root and installation key
+ 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);
cygwin_shared->initialize ();
user_shared_create (false);
}
cygwin_version.api_minor)
#define SHARED_VERSION_MAGIC CYGWIN_VERSION_MAGIC (SHARED_MAGIC, SHARED_VERSION)
-#define SHARED_INFO_CB 39328
+#define SHARED_INFO_CB 31136
-#define CURR_SHARED_MAGIC 0x22f9ff0bU
+#define CURR_SHARED_MAGIC 0x18da899eU
#define USER_VERSION 1 // increment when mount table changes and
#define USER_VERSION_MAGIC CYGWIN_VERSION_MAGIC (USER_MAGIC, USER_VERSION)
DWORD sys_mount_table_counter;
tty_list tty;
LONG last_used_bindresvport;
- WCHAR installation_root[PATH_MAX];
DWORD obcaseinsensitive;
mtinfo mt;
void initialize ();
- void init_installation_root ();
void init_obcaseinsensitive ();
unsigned heap_chunk_size ();
unsigned heap_slop_size ();
DWORD access = FILE_MAP_READ | FILE_MAP_WRITE);
extern void user_shared_create (bool reinit);
extern void user_shared_initialize ();
-
+extern void init_installation_root ();
+extern WCHAR installation_root[PATH_MAX];
+extern UNICODE_STRING installation_key;
curr_lines = 0;
if (!path &&
- !(path = (PWCHAR) malloc ((wcslen (cygwin_shared->installation_root)
+ !(path = (PWCHAR) malloc ((wcslen (installation_root)
+ wcslen (rel_path) + 1) * sizeof (WCHAR))))
{
paranoid_printf ("malloc (%W) failed", rel_path);
goto out;
}
- wcpcpy (wcpcpy (path, cygwin_shared->installation_root), rel_path);
+ wcpcpy (wcpcpy (path, installation_root), rel_path);
RtlInitUnicodeString (&upath, path);
InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL, NULL);