diff options
| author | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-02 05:16:33 +0000 |
|---|---|---|
| committer | bitflash-maintainer <noreply@bitflash.invalid> | 2026-09-02 06:47:24 +0000 |
| commit | 5ef59833756da6f47274cb990eb874fb0ed99019 (patch) | |
| tree | 450e0c22dee181f6d562c463e792ef0364250f08 /src | |
| parent | 18ffcb21393c9e54653844d62c5ef97c58bc61d4 (diff) | |
build: keep the stack non-executable, whoever links this
RandomX links jit_compiler_x86_static.S, a hand-written assembly stub with
no .note.GNU-stack marker. binutils reads a missing marker as a request for
an executable stack, and older linkers grant it for the whole binary: NX off,
process-wide, for a node that parses attacker-supplied blocks and messages.
The same source therefore produced different security properties depending on
where it was built. Ubuntu 26.04 gave GNU_STACK RW; Debian 12 -- the build
target for the deploy image, because it is the oldest glibc we ship to and the
last Debian that still packages the Berkeley DB C++ binding -- gave RWE. The
only announcement was a linker warning in the middle of an otherwise clean
build.
-z noexecstack settles it in the tree instead of in the toolchain. RandomX's
JIT maps its own W^X pages and never executes from the stack, so nothing that
works today stops working. Both link lines take it, GUI and headless.
Verify: readelf -lW bitflash-node | grep -A1 GNU_STACK # expect RW
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/src/Makefile b/src/Makefile index fe48041..8ea3930 100644 --- a/src/Makefile +++ b/src/Makefile | |||
| @@ -101,7 +101,7 @@ obj/imgui_impl_opengl3.o: $(IMGUI_DIR)/imgui_impl_opengl3.cpp | |||
| 101 | $(CXX) -c $(CXXFLAGS) -o $@ $< | 101 | $(CXX) -c $(CXXFLAGS) -o $@ $< |
| 102 | 102 | ||
| 103 | bitflash: $(IMGUI_OBJS) $(NODE_OBJS) $(GUI_OBJS) | 103 | bitflash: $(IMGUI_OBJS) $(NODE_OBJS) $(GUI_OBJS) |
| 104 | $(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS) | 104 | $(CXX) $(CXXFLAGS) $(LDHARDFLAGS) -o $@ $^ $(LIBS) |
| 105 | @echo "Built: bitflash" | 105 | @echo "Built: bitflash" |
| 106 | 106 | ||
| 107 | # ---- headless node --------------------------------------------------------- | 107 | # ---- headless node --------------------------------------------------------- |
| @@ -115,6 +115,20 @@ bitflash: $(IMGUI_OBJS) $(NODE_OBJS) $(GUI_OBJS) | |||
| 115 | # Objects go to obj-node/ because main_gui.cpp is compiled twice, with and | 115 | # Objects go to obj-node/ because main_gui.cpp is compiled twice, with and |
| 116 | # without -DBITFLASH_NO_GUI, and the two must not overwrite each other. | 116 | # without -DBITFLASH_NO_GUI, and the two must not overwrite each other. |
| 117 | 117 | ||
| 118 | # RandomX links a hand-written assembly JIT stub, jit_compiler_x86_static.S, | ||
| 119 | # which carries no .note.GNU-stack marker. Older binutils -- Debian 12's, which | ||
| 120 | # is what builds against the oldest glibc we ship to -- reads a missing marker | ||
| 121 | # as "this object wants an executable stack" and marks the whole binary RWE, | ||
| 122 | # switching NX off for the process. Newer toolchains default the other way, so | ||
| 123 | # identical source produced GNU_STACK RW on Ubuntu 26.04 and RWE on bookworm, | ||
| 124 | # announced by nothing louder than a linker warning in the middle of the build. | ||
| 125 | # | ||
| 126 | # Assert it here rather than inherit whichever default the build host happens | ||
| 127 | # to carry. The JIT maps its own W^X pages and never executes from the stack, | ||
| 128 | # so nothing needs the permission this takes away. Check with: | ||
| 129 | # readelf -lW bitflash-node | grep -A1 GNU_STACK # expect RW, not RWE | ||
| 130 | LDHARDFLAGS = -Wl,-z,noexecstack | ||
| 131 | |||
| 118 | NODE_LIBS = -L$(SECP_LIB) -lsecp256k1 \ | 132 | NODE_LIBS = -L$(SECP_LIB) -lsecp256k1 \ |
| 119 | -L$(RANDOMX_DIR)/build -lrandomx \ | 133 | -L$(RANDOMX_DIR)/build -lrandomx \ |
| 120 | -lsodium -lssl -lcrypto -ldb_cxx -lsqlite3 -lpthread | 134 | -lsodium -lssl -lcrypto -ldb_cxx -lsqlite3 -lpthread |
| @@ -135,7 +149,7 @@ obj-node/sha.o: sha.cpp sha.h | |||
| 135 | $(CXX) -c $(CXXFLAGS) -DBITFLASH_NO_GUI -O3 -o $@ $< | 149 | $(CXX) -c $(CXXFLAGS) -DBITFLASH_NO_GUI -O3 -o $@ $< |
| 136 | 150 | ||
| 137 | bitflash-node: $(NODE_ONLY_OBJS) | 151 | bitflash-node: $(NODE_ONLY_OBJS) |
| 138 | $(CXX) $(CXXFLAGS) -o $@ $^ $(NODE_LIBS) | 152 | $(CXX) $(CXXFLAGS) $(LDHARDFLAGS) -o $@ $^ $(NODE_LIBS) |
| 139 | @echo "Built: bitflash-node (headless, no libGL needed)" | 153 | @echo "Built: bitflash-node (headless, no libGL needed)" |
| 140 | 154 | ||
| 141 | obj-fuzz/%.o: %.cpp $(HEADERS) | 155 | obj-fuzz/%.o: %.cpp $(HEADERS) |