Cygwin: decouple shared mem regions from Cygwin DLL
Another reason ASLR may fail is the coupling of the standard shared mem regions (global, userinfo, process info, shared console) to the address of the Cygwin DLL. They are always placed in fixed addresses preceeding the Cygwin DLL's address. With ASLR this is bound to fail. Use a fixed, unused memory area to place the shared mem regions. This also allows to simplify the shared memory creation. There's no reason anymore to rebase the regions and rather than offsets, just use the addresses directly. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
2f9b8ff00c
commit
60675f1a7e
|
@ -32,6 +32,16 @@ details. */
|
||||||
dynamicbase is accidentally not set in the PE/COFF header of the DLL. */
|
dynamicbase is accidentally not set in the PE/COFF header of the DLL. */
|
||||||
#define CYGWIN_DLL_ADDRESS 0x180040000UL
|
#define CYGWIN_DLL_ADDRESS 0x180040000UL
|
||||||
|
|
||||||
|
/* New with ASLR: We need a fixed place for the global shared memory areas.
|
||||||
|
Prior to ASLR, the addresses were relative to the address the Cygwin DLL
|
||||||
|
was loaded to. */
|
||||||
|
#define SHARED_REGIONS_ADDRESS_LOW 0x1f0000000UL
|
||||||
|
#define CYGWIN_REGION_ADDRESS 0x1f0000000UL
|
||||||
|
#define USER_REGION_ADDRESS 0x1f2000000UL
|
||||||
|
#define PINFO_REGION_ADDRESS 0x1f4000000UL
|
||||||
|
#define SHARED_CONSOLE_REGION_ADDRESS 0x1f6000000UL
|
||||||
|
#define SHARED_REGIONS_ADDRESS_HIGH 0x200000000UL
|
||||||
|
|
||||||
/* Rebased DLLs are located in this 16 Gigs arena. Will be kept for
|
/* Rebased DLLs are located in this 16 Gigs arena. Will be kept for
|
||||||
backward compatibility. */
|
backward compatibility. */
|
||||||
#define REBASED_DLL_STORAGE_LOW 0x200000000UL
|
#define REBASED_DLL_STORAGE_LOW 0x200000000UL
|
||||||
|
|
|
@ -19,6 +19,7 @@ details. */
|
||||||
#include "shared_info_magic.h"
|
#include "shared_info_magic.h"
|
||||||
#include "registry.h"
|
#include "registry.h"
|
||||||
#include "cygwin_version.h"
|
#include "cygwin_version.h"
|
||||||
|
#include "memory_layout.h"
|
||||||
#include "spinlock.h"
|
#include "spinlock.h"
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
@ -112,29 +113,16 @@ shared_name (WCHAR *ret_buf, const WCHAR *str, int num)
|
||||||
#define page_const ((ptrdiff_t) 65535)
|
#define page_const ((ptrdiff_t) 65535)
|
||||||
#define pround(n) ((ptrdiff_t)(((n) + page_const) & ~page_const))
|
#define pround(n) ((ptrdiff_t)(((n) + page_const) & ~page_const))
|
||||||
|
|
||||||
/* The order in offsets is so that the constant blocks shared_info
|
/* FIXME: With ASLR, maybe we should ASLR the shared regions, too? */
|
||||||
and user_info are right below the cygwin DLL, then the pinfo block
|
static uintptr_t region_address[] =
|
||||||
which changes with each process. Below that is the console_state,
|
|
||||||
an optional block which only exists when running in a Windows console
|
|
||||||
window. Therefore, if we are not running in a console, we have 64K
|
|
||||||
more of contiguous memory below the Cygwin DLL. */
|
|
||||||
static ptrdiff_t offsets[] =
|
|
||||||
{
|
{
|
||||||
- pround (sizeof (shared_info)), /* SH_CYGWIN_SHARED */
|
CYGWIN_REGION_ADDRESS, /* SH_CYGWIN_SHARED */
|
||||||
- pround (sizeof (shared_info)) /* SH_USER_SHARED */
|
USER_REGION_ADDRESS, /* SH_USER_SHARED */
|
||||||
- pround (sizeof (user_info)),
|
PINFO_REGION_ADDRESS, /* SH_MYSELF */
|
||||||
- pround (sizeof (shared_info)) /* SH_MYSELF */
|
SHARED_CONSOLE_REGION_ADDRESS, /* SH_SHARED_CONSOLE */
|
||||||
- pround (sizeof (user_info))
|
|
||||||
- pround (sizeof (_pinfo)),
|
|
||||||
- pround (sizeof (shared_info)) /* SH_SHARED_CONSOLE */
|
|
||||||
- pround (sizeof (user_info))
|
|
||||||
- pround (sizeof (_pinfo))
|
|
||||||
- pround (sizeof (fhandler_console::console_state)),
|
|
||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
#define off_addr(x) ((void *)((caddr_t) cygwin_hmodule + offsets[x]))
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
open_shared (const WCHAR *name, int n, HANDLE& shared_h, DWORD size,
|
open_shared (const WCHAR *name, int n, HANDLE& shared_h, DWORD size,
|
||||||
shared_locations m, PSECURITY_ATTRIBUTES psa, DWORD access)
|
shared_locations m, PSECURITY_ATTRIBUTES psa, DWORD access)
|
||||||
|
@ -152,10 +140,7 @@ open_shared (const WCHAR *name, int n, HANDLE& shared_h, DWORD size,
|
||||||
if (*m == SH_JUSTCREATE || *m == SH_JUSTOPEN)
|
if (*m == SH_JUSTCREATE || *m == SH_JUSTOPEN)
|
||||||
addr = NULL;
|
addr = NULL;
|
||||||
else
|
else
|
||||||
{
|
addr = (void *) region_address[*m];
|
||||||
addr = off_addr (*m);
|
|
||||||
VirtualFree (addr, 0, MEM_RELEASE);
|
|
||||||
}
|
|
||||||
|
|
||||||
WCHAR map_buf[MAX_PATH];
|
WCHAR map_buf[MAX_PATH];
|
||||||
WCHAR *mapname = NULL;
|
WCHAR *mapname = NULL;
|
||||||
|
@ -185,33 +170,9 @@ open_shared (const WCHAR *name, int n, HANDLE& shared_h, DWORD size,
|
||||||
|
|
||||||
shared = (shared_info *) MapViewOfFileEx (shared_h, access, 0, 0, 0, addr);
|
shared = (shared_info *) MapViewOfFileEx (shared_h, access, 0, 0, 0, addr);
|
||||||
|
|
||||||
if (!shared && addr)
|
|
||||||
{
|
|
||||||
shared = (shared_info *) MapViewOfFileEx (shared_h,
|
|
||||||
FILE_MAP_READ|FILE_MAP_WRITE,
|
|
||||||
0, 0, 0, NULL);
|
|
||||||
#ifdef DEBUGGING
|
|
||||||
system_printf ("relocating shared object %W(%d) from %p to %p", name, n, addr, shared);
|
|
||||||
#endif
|
|
||||||
offsets[0] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!shared)
|
if (!shared)
|
||||||
api_fatal ("MapViewOfFileEx '%W'(%p), %E. Terminating.", mapname, shared_h);
|
api_fatal ("MapViewOfFileEx '%W'(%p), %E. Terminating.", mapname, shared_h);
|
||||||
|
|
||||||
if (*m == SH_CYGWIN_SHARED && offsets[0])
|
|
||||||
{
|
|
||||||
/* Reserve subsequent shared memory areas in non-relocated case only.
|
|
||||||
There's no good reason to reserve the console shmem, because it's
|
|
||||||
not yet known if we will allocate it at all. */
|
|
||||||
for (int i = SH_USER_SHARED; i < SH_SHARED_CONSOLE; i++)
|
|
||||||
{
|
|
||||||
DWORD size = offsets[i - 1] - offsets[i];
|
|
||||||
if (!VirtualAlloc (off_addr (i), size, MEM_RESERVE, PAGE_NOACCESS))
|
|
||||||
continue; /* oh well */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debug_printf ("name %W, n %d, shared %p (wanted %p), h %p, *m %d",
|
debug_printf ("name %W, n %d, shared %p (wanted %p), h %p, *m %d",
|
||||||
mapname, n, shared, addr, shared_h, *m);
|
mapname, n, shared, addr, shared_h, *m);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue