build: add optional hardened production flags - #1138
Conversation
|
Hi @DeusData, It looks like this PR is currently blocked by the From the workflow logs, the gate waits for the separate CodeQL workflow to complete, but the CodeQL run remained All other checks completed successfully. Would you mind re-running the CodeQL workflow (or the failed checks) for this PR? Thank you! |
|
Thanks for flagging the earlier timeout. The CodeQL workflow recovered without intervention and every check on exact head For the build direction, we do want production hardening, but not as a permanent FreeBSD-specific opt-in that leaves the standard release artifacts unchanged. Please rework this into a generic production-hardening policy: use platform/compiler capability rather than a FreeBSD name, enable the supported stack-protector, FORTIFY, RELRO, and immediate-binding protections by default for compatible ELF production builds, retain an explicit escape hatch for incompatible downstream toolchains, and leave sanitizer/test builds unchanged. The verification should inspect the produced standard artifacts for a non-executable stack, RELRO, and BIND_NOW where applicable. Keep this PR limited to that build policy; no unrelated build-system changes. |
|
Thanks for the detailed feedback. I'm glad to hear the goal of enabling production hardening aligns with the project's direction. My original Reworking this into a generic
Once I understand the intended scope, I'll rework the Makefile accordingly and keep this PR focused on the production hardening policy. |
|
One additional note related to the current hardening work. I've completed the FreeBSD porting work for both At the moment, the ports track my If you'd like to review the packaging, I've published the FreeBSD ports repository here: https://github.com/PR9000/codebase-memory-mcp-pkg It contains the FreeBSD port Makefiles, packaging metadata, build logs, and the generated One final question: do you have any preference regarding the |
|
For the initial implementation, target ELF production builds only: Linux and the BSDs. Leave macOS Mach-O and Windows PE behavior unchanged for now; those require different hardening policies and verification. Please build on the existing platform/compiler detection to select the ELF path, then use small compile/link capability probes for the individual hardening flags instead of keying behavior to a FreeBSD name. Enable supported hardening by default for compatible production builds, retain I see the head has moved to |
|
@DeusData The CI gate is failing because of test → daemon_application, not FAIL tests/test_daemon_application.c:2671: ASSERT(terminal_with_prior_subscribers) security, lint, changes, and pr-smoke all passed. Given it's a single Could you re-run the failed macos-14-cc job a couple of times so we can |
|
@DeusData Update: the daemon_application flakiness didn't reappear on the |
623b67b to
94c3b9a
Compare
|
@DeusData Update: Following recent updates on Just pushed two follow-up commits to restore full FreeBSD build compatibility:
|
Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
Enable production hardening by default for ELF targets (Linux and BSDs), using empirical compiler and linker capability probing instead of OS or toolchain assumptions. Key changes: - Detect ELF target format via compiler preprocessor (__ELF__ macro), using printf-based line construction for portable behavior across POSIX shells (dash, bash, FreeBSD sh). - Introduce empirical flag probing (probe_flag) using active CC/CXX drivers. - Dynamically detect and apply C/C++ compiler hardening flags: -fstack-protector-strong, -D_FORTIFY_SOURCE=2, -fPIE. - Dynamically detect and apply linker hardening flags: -Wl,-z,relro, -Wl,-z,now, -Wl,-z,noexecstack, -pie. - Propagate HARDEN_CFLAGS and HARDEN_CXXFLAGS to all production objects, including vendored components (mimalloc, sqlite3, tre, grammars, lz4, zstd). - Preserve opt-out escape hatch via PRODUCTION_HARDENING=0. - Retain backward compatibility for legacy HARDENING/FREEBSD_HARDENING variables. - Leave macOS Mach-O, Windows PE, and test/sanitizer builds unchanged. Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
…itions Building on FreeBSD after syncing with upstream failed with -Werror,-Wunused-function on activation_finish_absent_publish in src/cli/activation_transaction.c. The function is only invoked from three platform-specific branches: Windows (_WIN32, MoveFileExW), macOS (__APPLE__, renameatx_np), and modern Linux (__linux__ with SYS_renameat2, via syscall). On every other POSIX target — including FreeBSD and other BSDs — control falls through to the portable linkat(2) fallback, so the helper was defined but never called, tripping -Wunused-function under -Werror. Rather than excluding FreeBSD by name (which would still break on OpenBSD, NetBSD, DragonFly, Solaris, or any Linux without SYS_renameat2), wrap the function definition in the same #if condition as its call sites. This keeps the guard mechanically tied to actual usage instead of enumerating platforms, so it stays correct as new targets are added. Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
…robe
The ELF_BUILD probe used `printf '%s\n' '#ifndef __ELF__' ...` piped into
the preprocessor to detect ELF targets by triggering (or not) a #error.
This broke the macOS CI job with:
Makefile.cbm:146: *** unterminated call to function `shell':
missing `)'. Stop.
GNU Make treats `#` as a comment character even inside a $(shell ...)
call and even inside quoted strings, unless escaped with `\#`. macOS
ships GNU Make 3.81 (frozen pre-GPLv3), whose parser hit this literally
and swallowed the rest of the line, including the closing `)`. Linux and
FreeBSD builds didn't show this because they use newer GNU Make, which
happened to tolerate it.
Replace the #error-triggering probe with a direct macro check, matching
the existing IS_GCC/IS_MINGW probes in this file: dump predefined macros
via -dM -E and grep for __ELF__, which compilers define natively on ELF
targets. This removes every literal `#` from the Makefile text, so the
probe parses identically across GNU Make versions, and is more direct
than the previous #ifndef/#error round-trip.
Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
…PROC_PATHNAME) Extends FreeBSD support across process-image test suites: - tests/test_daemon_runtime.c: add FreeBSD sysctl self/peer path resolution, widen helper guards and test runner registrations. - tests/test_mcp.c: implement FreeBSD sysctl in idxfailclosed_self_path. - tests/test_watcher.c: implement FreeBSD sysctl in watcher_test_self_image and include __FreeBSD__ in blocked-git watcher tests. Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
4dc5fff to
fec8bd1
Compare
…profile and -lexecinfo Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
cbm_detect_self_path had no branch for FreeBSD, falling through to the generic #else that reads /proc/self/exe. In this environment /proc is a native FreeBSD procfs mount left empty (only /compat/linux/proc is populated, for Linux-ABI processes under the compat layer), so the readlink always failed silently and the function fell back to the expected install path instead of the actual running binary's path. This broke install: with no valid self path, the activation transaction could never confirm what to publish and aborted early with "activation transaction I/O failed" before attempting any linkat/rename. Add sysctl(CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1) for FreeBSD, matching the pattern already used in the test suites, and include <sys/sysctl.h> guarded by __FreeBSD__. Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
mimalloc's link-order override on POSIX assumes every allocation in the process image goes through mimalloc, but this doesn't hold universally — the same failure mode already documented for macOS's two-level namespace. On FreeBSD, some libc code paths may return pointers that were never allocated by mimalloc; freeing them via mi_free aborted with "mimalloc: error: mi_free: invalid pointer" during install. Add mem_override_is_ours() (mi_is_in_heap_region) and route __wrap_free/ __wrap_realloc through it: mimalloc-owned blocks go to mi_free/mi_realloc as before, anything else falls back to the real libc __real_free/ __real_realloc. Also fixes __wrap_realloc(NULL, size), which previously skipped the profiling-free call but still risked mixing allocators on the grow path. Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
Extends runtime_process_image_reference_* to support FreeBSD process image discovery and comparison. Previously this functionality was guarded only for _WIN32, __APPLE__, and __linux__. Uses sysctl(KERN_PROC_PATHNAME) to resolve a process's executable path without depending on procfs. Renames runtime_linux_stat_same_image to runtime_posix_stat_same_image now that the same comparison logic serves Linux, macOS, and FreeBSD. Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
private_log_directory_path_copy resolves a small allowlist of trusted top-level aliases before its component-wise O_NOFOLLOW path walk (Darwin's /tmp -> /private/tmp and /var -> /private/var). FreeBSD commonly exposes /home as a symlink to /usr/home. Treat it as a trusted root-owned alias so log directory paths under /home resolve correctly during the secure path walk. Signed-off-by: Pedro Ramos <131530838+pr9000@users.noreply.github.com>
fec8bd1 to
450a21f
Compare
What does this PR do?
Add an optional, non-intrusive production hardening option in
Makefile.cbm.This change was prepared alongside PR #1093 (
fix(foundation): use HW_PHYSMEM for physical memory detection on FreeBSD), but was split into a separate PR to keep the scope focused.The new
FREEBSD_HARDENINGoption supports hardened downstream packaging environments (for example, FreeBSD Ports Collection).Details
When enabled via
FREEBSD_HARDENING=1, production builds (cbmandcbm-with-ui) receive:-fstack-protector-strong-D_FORTIFY_SOURCE=2-Wl,-z,relro -Wl,-z,nowThe implementation keeps upstream impact minimal:
0), so existing builds, CI pipelines, and developer workflows are unchanged.CFLAGS_PROD,CXXFLAGS_PROD, andLDFLAGS.HARDEN_CFLAGSandHARDEN_LDFLAGSvariables to keep the build logic portable.Verified this locally on FreeBSD 15.1:
The resulting ELF binary was verified with:
Output:
and:
Output:
Both production targets were verified successfully with the hardening option enabled.
Checklist
git commit -s) — required, CI rejectsunsigned commits (DCO, see CONTRIBUTING.md)
make -f Makefile.cbm test)make -f Makefile.cbm lint-ci)