Index | Thread | Search

From:
Kirill A. Korinsky <kirill@korins.ky>
Subject:
Allocated WebAssembly stack memory with MAP_STACK in firefoxes
To:
Leah Rowe <leah@libreboot.org>, Landry Breuil <landry@openbsd.org>
Cc:
OpenBSD ports <ports@openbsd.org>
Date:
Sun, 27 Sep 2026 00:14:05 +0200

Download raw body.

Thread
Folks,

I'd like to backport a fix for WebAssembly which leads to crash of firefox,
see: https://bugzilla.mozilla.org/show_bug.cgi?id=2074025

Almost the same fix was backported to chromiums.

As I understand only Librefox and two Firefox needs it.

Ok?

Index: www/firefox-esr/Makefile
===================================================================
RCS file: /cvs/ports/www/firefox-esr/Makefile,v
diff -u -p -r1.280 Makefile
--- www/firefox-esr/Makefile	15 Sep 2026 12:44:26 -0000	1.280
+++ www/firefox-esr/Makefile	26 Sep 2026 22:10:26 -0000
@@ -2,6 +2,7 @@ COMMENT =	Firefox web browser, Extended 
 ONLY_FOR_ARCHS =	amd64 aarch64 riscv64
 
 MOZILLA_VERSION =	153.3.0esr
+REVISION =		0
 MOZILLA_BRANCH =	release
 MOZILLA_PROJECT =	firefox-esr
 MOZILLA_CODENAME =	browser
Index: www/firefox-esr/patches/patch-js_src_gc_Memory_cpp
===================================================================
RCS file: www/firefox-esr/patches/patch-js_src_gc_Memory_cpp
diff -N www/firefox-esr/patches/patch-js_src_gc_Memory_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ www/firefox-esr/patches/patch-js_src_gc_Memory_cpp	26 Sep 2026 22:10:26 -0000
@@ -0,0 +1,36 @@
+https://hg.mozilla.org/mozilla-central/rev/b3a14f8efa23
+
+Index: js/src/gc/Memory.cpp
+--- js/src/gc/Memory.cpp.orig
++++ js/src/gc/Memory.cpp
+@@ -530,6 +530,30 @@ void MapStack(size_t stackSize) {
+ #endif
+ }
+ 
++void* MapAlignedPagesAsStack(size_t length, size_t alignment,
++                             StallAndRetry stallAndRetry) {
++  void* region = MapAlignedPages(length, alignment, stallAndRetry);
++  if (!region) {
++    return nullptr;
++  }
++
++#ifdef __OpenBSD__
++  // OpenBSD kills the process if the stack pointer points into memory not
++  // mapped with MAP_STACK. That flag can only be set at mmap() time, so remap
++  // the region in place. The pages are freshly mapped and untouched, so
++  // discarding their contents here is fine.
++  void* result = MozTaggedAnonymousMmap(
++      region, length, int(PageAccess::ReadWrite),
++      MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_STACK, -1, 0, "js-gc-stack");
++  if (result != region) {
++    UnmapPages(region, length);
++    return nullptr;
++  }
++#endif
++
++  return region;
++}
++
+ void CheckMemorySubsystemOnShutDown() {
+   MOZ_ASSERT(gMappedMemorySizeBytes == 0);
+ }
Index: www/firefox-esr/patches/patch-js_src_gc_Memory_h
===================================================================
RCS file: www/firefox-esr/patches/patch-js_src_gc_Memory_h
diff -N www/firefox-esr/patches/patch-js_src_gc_Memory_h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ www/firefox-esr/patches/patch-js_src_gc_Memory_h	26 Sep 2026 22:10:26 -0000
@@ -0,0 +1,18 @@
+https://hg.mozilla.org/mozilla-central/rev/b3a14f8efa23
+
+Index: js/src/gc/Memory.h
+--- js/src/gc/Memory.h.orig
++++ js/src/gc/Memory.h
+@@ -56,6 +56,12 @@ void UnmapPages(void* region, size_t length);
+ // the space that the stack may expand into. (Only on Linux fuzzing builds.)
+ void MapStack(size_t stackSize);
+ 
++// Like MapAlignedPages, but the returned region is also usable as a call stack.
++// Some systems (notably OpenBSD) terminate the process if the stack pointer
++// points into memory that was not mapped with MAP_STACK.
++void* MapAlignedPagesAsStack(size_t length, size_t alignment,
++                             StallAndRetry stallAndRetry = StallAndRetry::No);
++
+ // We only decommit unused pages if the system page size is the same as the
+ // hardcoded page size for the build.
+ bool DecommitEnabled();
Index: www/firefox-esr/patches/patch-js_src_wasm_WasmStacks_cpp
===================================================================
RCS file: www/firefox-esr/patches/patch-js_src_wasm_WasmStacks_cpp
diff -N www/firefox-esr/patches/patch-js_src_wasm_WasmStacks_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ www/firefox-esr/patches/patch-js_src_wasm_WasmStacks_cpp	26 Sep 2026 22:10:26 -0000
@@ -0,0 +1,14 @@
+https://hg.mozilla.org/mozilla-central/rev/b3a14f8efa23
+
+Index: js/src/wasm/WasmStacks.cpp
+--- js/src/wasm/WasmStacks.cpp.orig
++++ js/src/wasm/WasmStacks.cpp
+@@ -816,7 +816,7 @@ ContStackArena::~ContStackArena() {
+ /* static */
+ UniqueContStackArena ContStackArena::create(ContStackAllocator* owner) {
+   size_t arenaSize = owner->arenaSize();
+-  void* arenaBase = gc::MapAlignedPages(arenaSize, ContStackAlignment);
++  void* arenaBase = gc::MapAlignedPagesAsStack(arenaSize, ContStackAlignment);
+   if (!arenaBase) {
+     return nullptr;
+   }
Index: www/librewolf/Makefile
===================================================================
RCS file: /cvs/ports/www/librewolf/Makefile,v
diff -u -p -r1.20 Makefile
--- www/librewolf/Makefile	17 Sep 2026 05:47:29 -0000	1.20
+++ www/librewolf/Makefile	26 Sep 2026 22:10:27 -0000
@@ -14,6 +14,7 @@ ONLY_FOR_ARCHS =	amd64 aarch64 riscv64
 # If upstream adds revision number -x, it will become plx in OpenBSD, e.g.
 # librewolf-149.0.2-2 (upstream) becomes librewolf-149.0.2pl2 (patch level 2)
 MOZILLA_DIST_VERSION =	156.0-1
+REVISION =		0
 MOZILLA_VERSION =	${MOZILLA_DIST_VERSION:C/-([0-9]+)$/pl\1/}
 
 MOZILLA_PROJECT =	librewolf
Index: www/librewolf/patches/patch-js_src_gc_Memory_cpp
===================================================================
RCS file: www/librewolf/patches/patch-js_src_gc_Memory_cpp
diff -N www/librewolf/patches/patch-js_src_gc_Memory_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ www/librewolf/patches/patch-js_src_gc_Memory_cpp	26 Sep 2026 22:10:27 -0000
@@ -0,0 +1,36 @@
+https://hg.mozilla.org/mozilla-central/rev/b3a14f8efa23
+
+Index: js/src/gc/Memory.cpp
+--- js/src/gc/Memory.cpp.orig
++++ js/src/gc/Memory.cpp
+@@ -532,6 +532,30 @@ void MapStack(size_t stackSize) {
+ #endif
+ }
+ 
++void* MapAlignedPagesAsStack(size_t length, size_t alignment,
++                             StallAndRetry stallAndRetry) {
++  void* region = MapAlignedPages(length, alignment, stallAndRetry);
++  if (!region) {
++    return nullptr;
++  }
++
++#ifdef __OpenBSD__
++  // OpenBSD kills the process if the stack pointer points into memory not
++  // mapped with MAP_STACK. That flag can only be set at mmap() time, so remap
++  // the region in place. The pages are freshly mapped and untouched, so
++  // discarding their contents here is fine.
++  void* result = MozTaggedAnonymousMmap(
++      region, length, int(PageAccess::ReadWrite),
++      MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_STACK, -1, 0, "js-gc-stack");
++  if (result != region) {
++    UnmapPages(region, length);
++    return nullptr;
++  }
++#endif
++
++  return region;
++}
++
+ void CheckMemorySubsystemOnShutDown() {
+   MOZ_ASSERT(gMappedMemorySizeBytes == 0);
+ }
Index: www/librewolf/patches/patch-js_src_gc_Memory_h
===================================================================
RCS file: www/librewolf/patches/patch-js_src_gc_Memory_h
diff -N www/librewolf/patches/patch-js_src_gc_Memory_h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ www/librewolf/patches/patch-js_src_gc_Memory_h	26 Sep 2026 22:10:27 -0000
@@ -0,0 +1,18 @@
+https://hg.mozilla.org/mozilla-central/rev/b3a14f8efa23
+
+Index: js/src/gc/Memory.h
+--- js/src/gc/Memory.h.orig
++++ js/src/gc/Memory.h
+@@ -56,6 +56,12 @@ void UnmapPages(void* region, size_t length);
+ // the space that the stack may expand into. (Only on Linux fuzzing builds.)
+ void MapStack(size_t stackSize);
+ 
++// Like MapAlignedPages, but the returned region is also usable as a call stack.
++// Some systems (notably OpenBSD) terminate the process if the stack pointer
++// points into memory that was not mapped with MAP_STACK.
++void* MapAlignedPagesAsStack(size_t length, size_t alignment,
++                             StallAndRetry stallAndRetry = StallAndRetry::No);
++
+ // We only decommit unused pages if the system page size is the same as the
+ // hardcoded page size for the build.
+ bool DecommitEnabled();
Index: www/librewolf/patches/patch-js_src_wasm_WasmStacks_cpp
===================================================================
RCS file: www/librewolf/patches/patch-js_src_wasm_WasmStacks_cpp
diff -N www/librewolf/patches/patch-js_src_wasm_WasmStacks_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ www/librewolf/patches/patch-js_src_wasm_WasmStacks_cpp	26 Sep 2026 22:10:27 -0000
@@ -0,0 +1,14 @@
+https://hg.mozilla.org/mozilla-central/rev/b3a14f8efa23
+
+Index: js/src/wasm/WasmStacks.cpp
+--- js/src/wasm/WasmStacks.cpp.orig
++++ js/src/wasm/WasmStacks.cpp
+@@ -874,7 +874,7 @@ ContStackArena::~ContStackArena() {
+ /* static */
+ UniqueContStackArena ContStackArena::create(ContStackAllocator* owner) {
+   size_t arenaSize = owner->arenaSize();
+-  void* arenaBase = gc::MapAlignedPages(arenaSize, ContStackAlignment);
++  void* arenaBase = gc::MapAlignedPagesAsStack(arenaSize, ContStackAlignment);
+   if (!arenaBase) {
+     return nullptr;
+   }
Index: www/mozilla-firefox/Makefile
===================================================================
RCS file: /cvs/ports/www/mozilla-firefox/Makefile,v
diff -u -p -r1.710 Makefile
--- www/mozilla-firefox/Makefile	22 Sep 2026 13:03:23 -0000	1.710
+++ www/mozilla-firefox/Makefile	26 Sep 2026 22:10:27 -0000
@@ -4,6 +4,7 @@ ONLY_FOR_ARCHS =	amd64 aarch64 riscv64
 # Don't forget to bump www/firefox-i18n after updates.
 
 MOZILLA_VERSION =	156.0.1
+REVISION =		0
 MOZILLA_BRANCH =	release
 MOZILLA_PROJECT =	firefox
 MOZILLA_CODENAME =	browser
Index: www/mozilla-firefox/patches/patch-js_src_gc_Memory_cpp
===================================================================
RCS file: www/mozilla-firefox/patches/patch-js_src_gc_Memory_cpp
diff -N www/mozilla-firefox/patches/patch-js_src_gc_Memory_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ www/mozilla-firefox/patches/patch-js_src_gc_Memory_cpp	26 Sep 2026 22:10:27 -0000
@@ -0,0 +1,36 @@
+https://hg.mozilla.org/mozilla-central/rev/b3a14f8efa23
+
+Index: js/src/gc/Memory.cpp
+--- js/src/gc/Memory.cpp.orig
++++ js/src/gc/Memory.cpp
+@@ -532,6 +532,30 @@ void MapStack(size_t stackSize) {
+ #endif
+ }
+ 
++void* MapAlignedPagesAsStack(size_t length, size_t alignment,
++                             StallAndRetry stallAndRetry) {
++  void* region = MapAlignedPages(length, alignment, stallAndRetry);
++  if (!region) {
++    return nullptr;
++  }
++
++#ifdef __OpenBSD__
++  // OpenBSD kills the process if the stack pointer points into memory not
++  // mapped with MAP_STACK. That flag can only be set at mmap() time, so remap
++  // the region in place. The pages are freshly mapped and untouched, so
++  // discarding their contents here is fine.
++  void* result = MozTaggedAnonymousMmap(
++      region, length, int(PageAccess::ReadWrite),
++      MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_STACK, -1, 0, "js-gc-stack");
++  if (result != region) {
++    UnmapPages(region, length);
++    return nullptr;
++  }
++#endif
++
++  return region;
++}
++
+ void CheckMemorySubsystemOnShutDown() {
+   MOZ_ASSERT(gMappedMemorySizeBytes == 0);
+ }
Index: www/mozilla-firefox/patches/patch-js_src_gc_Memory_h
===================================================================
RCS file: www/mozilla-firefox/patches/patch-js_src_gc_Memory_h
diff -N www/mozilla-firefox/patches/patch-js_src_gc_Memory_h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ www/mozilla-firefox/patches/patch-js_src_gc_Memory_h	26 Sep 2026 22:10:27 -0000
@@ -0,0 +1,18 @@
+https://hg.mozilla.org/mozilla-central/rev/b3a14f8efa23
+
+Index: js/src/gc/Memory.h
+--- js/src/gc/Memory.h.orig
++++ js/src/gc/Memory.h
+@@ -56,6 +56,12 @@ void UnmapPages(void* region, size_t length);
+ // the space that the stack may expand into. (Only on Linux fuzzing builds.)
+ void MapStack(size_t stackSize);
+ 
++// Like MapAlignedPages, but the returned region is also usable as a call stack.
++// Some systems (notably OpenBSD) terminate the process if the stack pointer
++// points into memory that was not mapped with MAP_STACK.
++void* MapAlignedPagesAsStack(size_t length, size_t alignment,
++                             StallAndRetry stallAndRetry = StallAndRetry::No);
++
+ // We only decommit unused pages if the system page size is the same as the
+ // hardcoded page size for the build.
+ bool DecommitEnabled();
Index: www/mozilla-firefox/patches/patch-js_src_wasm_WasmStacks_cpp
===================================================================
RCS file: www/mozilla-firefox/patches/patch-js_src_wasm_WasmStacks_cpp
diff -N www/mozilla-firefox/patches/patch-js_src_wasm_WasmStacks_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ www/mozilla-firefox/patches/patch-js_src_wasm_WasmStacks_cpp	26 Sep 2026 22:10:27 -0000
@@ -0,0 +1,14 @@
+https://hg.mozilla.org/mozilla-central/rev/b3a14f8efa23
+
+Index: js/src/wasm/WasmStacks.cpp
+--- js/src/wasm/WasmStacks.cpp.orig
++++ js/src/wasm/WasmStacks.cpp
+@@ -874,7 +874,7 @@ ContStackArena::~ContStackArena() {
+ /* static */
+ UniqueContStackArena ContStackArena::create(ContStackAllocator* owner) {
+   size_t arenaSize = owner->arenaSize();
+-  void* arenaBase = gc::MapAlignedPages(arenaSize, ContStackAlignment);
++  void* arenaBase = gc::MapAlignedPagesAsStack(arenaSize, ContStackAlignment);
+   if (!arenaBase) {
+     return nullptr;
+   }


-- 
wbr, Kirill