public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: decouple cygheap from Cygwin DLL
@ 2022-10-28 14:27 Corinna Vinschen
  0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2022-10-28 14:27 UTC (permalink / raw)
  To: cygwin-cvs

https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=2f9b8ff00cce0d0ceeb1091b6b9aecae914ddb89

commit 2f9b8ff00cce0d0ceeb1091b6b9aecae914ddb89
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Wed Oct 26 21:16:35 2022 +0200

    Cygwin: decouple cygheap from Cygwin DLL
    
    One reason that ASLR is tricky is the fact that the cygheap
    is placed at the end of the DLL and especially that it's expected
    to be growable.  To support ASLR, this construct must go.
    
    Define dedicated cygheap memory region and reserve entire region.
    Commit 3 Megs, as was the default size of the cygheap before.
    
    Fix linker script accordingly, drop a now useless version check
    in get_cygwin_startup_info().

Diff:
---
 winsup/cygwin/cygwin.sc.in                   | 21 +++-------
 winsup/cygwin/dcrt0.cc                       |  3 --
 winsup/cygwin/local_includes/cygheap.h       |  1 -
 winsup/cygwin/local_includes/memory_layout.h |  8 +++-
 winsup/cygwin/mm/cygheap.cc                  | 62 +++++++++++++++++-----------
 5 files changed, 50 insertions(+), 45 deletions(-)

diff --git a/winsup/cygwin/cygwin.sc.in b/winsup/cygwin/cygwin.sc.in
index 742f599e0..d984c51c9 100644
--- a/winsup/cygwin/cygwin.sc.in
+++ b/winsup/cygwin/cygwin.sc.in
@@ -111,6 +111,11 @@ SECTIONS
     SORT(*)(.idata$7)
     . = ALIGN(16);
   }
+  .rsrc BLOCK(__section_alignment__) :
+  {
+    *(.rsrc)
+    *(SORT(.rsrc$*))
+  }
   .gnu_debuglink_overlay ALIGN(__section_alignment__) (NOLOAD):
   {
     BYTE(0)	/* c */
@@ -127,22 +132,6 @@ SECTIONS
     BYTE(0)	/* \0 */
     LONG(0)	/* checksum */
   }
-  .rsrc BLOCK(__section_alignment__) :
-  {
-    *(.rsrc)
-    *(SORT(.rsrc$*))
-    _SYM (_cygheap_start) = .;
-  }
-  .cygheap ALIGN(__section_alignment__) :
-  {
-#ifdef __x86_64__
-    . = . + (3072 * 1024);
-#else
-    . = . + (2048 * 1024);
-#endif
-    . = ALIGN(0x10000);
-    _SYM (_cygheap_end) = .;
-  }
   /DISCARD/ :
   {
     *(.debug$S)
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index e1197092e..84db38cfe 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -527,9 +527,6 @@ get_cygwin_startup_info ()
     {
       if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
 	multiple_cygwin_problem ("proc intro", res->intro, 0);
-      else if (res->cygheap != (void *) &_cygheap_start)
-	multiple_cygwin_problem ("cygheap base", (uintptr_t) res->cygheap,
-				 (uintptr_t) &_cygheap_start);
 
       unsigned should_be_cb = 0;
       switch (res->type)
diff --git a/winsup/cygwin/local_includes/cygheap.h b/winsup/cygwin/local_includes/cygheap.h
index 6a844babd..4448983ab 100644
--- a/winsup/cygwin/local_includes/cygheap.h
+++ b/winsup/cygwin/local_includes/cygheap.h
@@ -727,4 +727,3 @@ class cygheap_fdenum : public cygheap_fdmanip
 void cygheap_fixup_in_child (bool);
 void cygheap_init ();
 void setup_cygheap ();
-extern char _cygheap_start[] __attribute__((section(".idata")));
diff --git a/winsup/cygwin/local_includes/memory_layout.h b/winsup/cygwin/local_includes/memory_layout.h
index 77ab61984..639ff2546 100644
--- a/winsup/cygwin/local_includes/memory_layout.h
+++ b/winsup/cygwin/local_includes/memory_layout.h
@@ -46,11 +46,17 @@ details. */
 #define THREAD_STORAGE_LOW		0x600000000UL
 #define THREAD_STORAGE_HIGH		0x800000000UL
 
+/* That's where the cygheap is located. CYGHEAP_STORAGE_INITIAL defines the
+   end of the initially committed heap area. */
+#define CYGHEAP_STORAGE_LOW		0x800000000UL
+#define CYGHEAP_STORAGE_INITIAL		0x800300000UL
+#define CYGHEAP_STORAGE_HIGH		0xa00000000UL
+
 /* This is where the user heap starts.  There's no defined end address.
    The user heap pontentially grows into the mmap arena.  However,
    the user heap grows upwar4ds and the mmap arena grows downwards,
    so there's not much chance to meet unluckily. */
-#define USERHEAP_START			0x800000000UL
+#define USERHEAP_START			0xa00000000UL
 
 /* The memory region used for memory maps.
    Up to Win 8 only 44 bit address space, 48 bit starting witrh 8.1, so
diff --git a/winsup/cygwin/mm/cygheap.cc b/winsup/cygwin/mm/cygheap.cc
index 65f95c924..ac8df6a82 100644
--- a/winsup/cygwin/mm/cygheap.cc
+++ b/winsup/cygwin/mm/cygheap.cc
@@ -22,6 +22,7 @@
 #include "pinfo.h"
 #include "registry.h"
 #include "ntdll.h"
+#include "memory_layout.h"
 #include <unistd.h>
 #include <wchar.h>
 #include <sys/param.h>
@@ -34,8 +35,6 @@ static mini_cygheap NO_COPY cygheap_dummy =
 init_cygheap NO_COPY *cygheap = (init_cygheap *) &cygheap_dummy;
 void NO_COPY *cygheap_max;
 
-extern "C" char  _cygheap_end[];
-
 static NO_COPY muto cygheap_protect;
 
 struct cygheap_entry
@@ -72,12 +71,31 @@ static void _cfree (void *);
 static void *_csbrk (int);
 }
 
+#define nextpage(x) ((char *) roundup2 ((uintptr_t) (x), \
+					wincap.allocation_granularity ()))
+#define allocsize(x) ((SIZE_T) nextpage (x))
+#ifdef DEBUGGING
+#define somekinda_printf debug_printf
+#else
+#define somekinda_printf malloc_printf
+#endif
+
 /* Called by fork or spawn to reallocate cygwin heap */
 void
 cygheap_fixup_in_child (bool execed)
 {
-  cygheap_max = cygheap = (init_cygheap *) _cygheap_start;
-  _csbrk ((char *) child_proc_info->cygheap_max - (char *) cygheap);
+  SIZE_T commit_size = CYGHEAP_STORAGE_INITIAL - CYGHEAP_STORAGE_LOW;
+
+  if (child_proc_info->cygheap_max > (void *) CYGHEAP_STORAGE_INITIAL)
+    commit_size = allocsize (child_proc_info->cygheap_max);
+  cygheap = (init_cygheap *) VirtualAlloc ((LPVOID) CYGHEAP_STORAGE_LOW,
+					   CYGHEAP_STORAGE_HIGH
+					   - CYGHEAP_STORAGE_LOW,
+					   MEM_RESERVE, PAGE_NOACCESS);
+  cygheap = (init_cygheap *) VirtualAlloc ((LPVOID) CYGHEAP_STORAGE_LOW,
+					   commit_size, MEM_COMMIT,
+					   PAGE_READWRITE);
+  cygheap_max = child_proc_info->cygheap_max;
   child_copy (child_proc_info->parent, false, child_proc_info->silentfail (),
 	      "cygheap", cygheap, cygheap_max, NULL);
   cygheap_init ();
@@ -245,15 +263,19 @@ cygheap_init ()
   cygheap_protect.init ("cygheap_protect");
   if (cygheap == &cygheap_dummy)
     {
-      cygheap = (init_cygheap *) memset (_cygheap_start, 0,
-					 sizeof (*cygheap));
-      cygheap_max = cygheap;
-      _csbrk (sizeof (*cygheap));
+      cygheap = (init_cygheap *) VirtualAlloc ((LPVOID) CYGHEAP_STORAGE_LOW,
+					       CYGHEAP_STORAGE_HIGH
+					       - CYGHEAP_STORAGE_LOW,
+					       MEM_RESERVE, PAGE_NOACCESS);
+      cygheap = (init_cygheap *) VirtualAlloc ((LPVOID) CYGHEAP_STORAGE_LOW,
+					       CYGHEAP_STORAGE_INITIAL
+					       - CYGHEAP_STORAGE_LOW,
+					       MEM_COMMIT, PAGE_READWRITE);
+      cygheap_max = (char *) cygheap + sizeof (*cygheap);
       /* Initialize bucket_val.  The value is the max size of a block
          fitting into the bucket.  The values are powers of two and their
-	 medians: 12, 16, 24, 32, 48, 64, ...  On 64 bit, start with 24 to
-	 accommodate bigger size of struct cygheap_entry.
-	 With NBUCKETS == 40, the maximum block size is 6291456/12582912.
+	 medians: 24, 32, 48, 64, ...  With NBUCKETS == 40, the maximum
+	 block size is 12582912.
 	 The idea is to have better matching bucket sizes (not wasting
 	 space) without trading in performance compared to the old powers
 	 of 2 method. */
@@ -284,30 +306,22 @@ setup_cygheap ()
   cygheap->pg.init ();
 }
 
-#define nextpage(x) ((char *) roundup2 ((uintptr_t) (x), \
-					wincap.allocation_granularity ()))
-#define allocsize(x) ((SIZE_T) nextpage (x))
-#ifdef DEBUGGING
-#define somekinda_printf debug_printf
-#else
-#define somekinda_printf malloc_printf
-#endif
-
 static void *
 _csbrk (int sbs)
 {
   void *prebrk = cygheap_max;
   char *newbase = nextpage (prebrk);
   cygheap_max = (char *) cygheap_max + sbs;
-  if (!sbs || (newbase >= cygheap_max) || (cygheap_max <= _cygheap_end))
+  if (!sbs || newbase >= cygheap_max
+      || cygheap_max <= (void *) CYGHEAP_STORAGE_INITIAL)
     /* nothing to do */;
   else
     {
-      if (prebrk <= _cygheap_end)
-	newbase = _cygheap_end;
+      if (prebrk <= (void *) CYGHEAP_STORAGE_INITIAL)
+	newbase = (char *) CYGHEAP_STORAGE_INITIAL;
 
       SIZE_T adjsbs = allocsize ((char *) cygheap_max - newbase);
-      if (adjsbs && !VirtualAlloc (newbase, adjsbs, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE))
+      if (adjsbs && !VirtualAlloc (newbase, adjsbs, MEM_COMMIT, PAGE_READWRITE))
 	{
 	  MEMORY_BASIC_INFORMATION m;
 	  if (!VirtualQuery (newbase, &m, sizeof m))

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-10-28 14:27 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-28 14:27 [newlib-cygwin] Cygwin: decouple cygheap from Cygwin DLL Corinna Vinschen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).