diff --git a/base/comps/azl-bootstrap-hardening/azl-bootstrap-hardening.comp.toml b/base/comps/azl-bootstrap-hardening/azl-bootstrap-hardening.comp.toml new file mode 100644 index 00000000000..ad9dd853863 --- /dev/null +++ b/base/comps/azl-bootstrap-hardening/azl-bootstrap-hardening.comp.toml @@ -0,0 +1,14 @@ +# Tiny local-spec package that ships a macros.d drop-in to enable +# distro-wide hardening flags for stage1 builds. Mechanism mirrors how +# azurelinux-rpm-config layers on top of redhat-rpm-config — this pkg +# just adds the hardening macros without touching redhat-rpm-config. +# +# Intent: any spec that BuildRequires this package (or any buildroot that +# pre-installs it) gets %_hardened_build=1 plus appended global compiler +# and linker flags before %set_build_flags composes CFLAGS/LDFLAGS. +# +# Used to A/B against Option A (per-component build.defines) on the +# dracut pilot. See base/comps/dracut/dracut.comp.toml. +[components.azl-bootstrap-hardening] +spec = { type = "local", path = "azl-bootstrap-hardening.spec" } +release = { calculation = "manual" } diff --git a/base/comps/azl-bootstrap-hardening/azl-bootstrap-hardening.spec b/base/comps/azl-bootstrap-hardening/azl-bootstrap-hardening.spec new file mode 100644 index 00000000000..b765df14313 --- /dev/null +++ b/base/comps/azl-bootstrap-hardening/azl-bootstrap-hardening.spec @@ -0,0 +1,36 @@ +Name: azl-bootstrap-hardening +Version: 1 +Release: 1%{?dist} +Summary: Stage1 BinSkim hardening macros for Azure Linux +License: MIT +URL: https://aka.ms/azurelinux +BuildArch: noarch + +Source0: macros.azl-bootstrap-hardening + +# rpm reads /usr/lib/rpm/macros.d/* at startup, so installing this drop-in +# is the only thing we need to do — no scriptlets required. +Requires: redhat-rpm-config + +%description +Layers Azure Linux stage1 compiler/linker hardening defaults on top of +Fedora's redhat-rpm-config via a /usr/lib/rpm/macros.d/ drop-in. Pilot +package used to evaluate distro-wide BinSkim remediation for the +azl4-bootstrap-compliance build target before broader rollout. + +%prep +# Nothing to unpack. + +%build +# Nothing to build. + +%install +install -d %{buildroot}%{_rpmconfigdir}/macros.d +install -m 0644 %{SOURCE0} %{buildroot}%{_rpmconfigdir}/macros.d/macros.azl-bootstrap-hardening + +%files +%{_rpmconfigdir}/macros.d/macros.azl-bootstrap-hardening + +%changelog +* Tue May 27 2026 Azure Linux Team - 1-1 +- Initial package for stage1 hardening flag rollout pilot. diff --git a/base/comps/azl-bootstrap-hardening/macros.azl-bootstrap-hardening b/base/comps/azl-bootstrap-hardening/macros.azl-bootstrap-hardening new file mode 100644 index 00000000000..0a4b6fab2ec --- /dev/null +++ b/base/comps/azl-bootstrap-hardening/macros.azl-bootstrap-hardening @@ -0,0 +1,27 @@ +# macros.azl-bootstrap-hardening +# +# Distro-wide hardening defaults for stage1 builds. Layered ON TOP of +# Fedora's redhat-rpm-config via macros.d drop-in priority — does not +# fork or replace any redhat-rpm-config file. +# +# Effect: when this package is installed in the buildroot, any spec that +# uses %configure / %cmake / %meson / %make_build / %set_build_flags +# picks up these flags. Build systems that bypass those macros and call +# the compiler directly will still need per-spec fixes. +# +# Pilot scope: dracut (see base/comps/dracut/dracut.comp.toml). +# Distro-wide rollout will inject this package into the stage1 mock +# chroot_setup_cmd once the pilot results are good. + +# Toggle Fedora's redhat-hardened-cc1 / redhat-hardened-ld spec files. +# Covers PIE, RELRO+now, stack protector, fortify on packages that +# honor Fedora's hardening hooks. +%_hardened_build 1 + +# Explicit appends for build systems that override %optflags / LDFLAGS +# but still respect %__global_compiler_flags / %__global_ldflags via +# %set_build_flags. Arch-guard CET (only meaningful on x86_64). +%__global_compiler_flags %{__global_compiler_flags} -fstack-protector-strong -fstack-clash-protection -fPIE -D_FORTIFY_SOURCE=3 %{?_cet_flag} +%__global_ldflags %{__global_ldflags} -Wl,-z,relro,-z,now -Wl,-z,noexecstack -pie + +%_cet_flag %{lua: if rpm.expand("%{_target_cpu}") == "x86_64" then print("-fcf-protection=full") end} diff --git a/base/comps/components.toml b/base/comps/components.toml index e460cc32019..3369a929cd1 100644 --- a/base/comps/components.toml +++ b/base/comps/components.toml @@ -348,7 +348,7 @@ includes = ["**/*.comp.toml", "component-check-disablement.toml", "component-min [components.doxygen] [components.dpdk] [components.dpkg] -[components.dracut] +# dracut: see base/comps/dracut/dracut.comp.toml (hardening-flag evaluation) [components.driverctl] [components.drpm] [components.duktape] diff --git a/base/comps/dracut/dracut.comp.toml b/base/comps/dracut/dracut.comp.toml new file mode 100644 index 00000000000..da8823afe4d --- /dev/null +++ b/base/comps/dracut/dracut.comp.toml @@ -0,0 +1,38 @@ +# dracut — used as a pilot package for evaluating stage1 BinSkim-hardening +# remediation options. We failed 802 packages in azl4-bootstrap-compliance with +# BA3001 (PIE), BA3003 (stack protector), BA3011 (RELRO). This file stages two +# mechanisms for injecting the hardening flags so we can A/B them. +# +# Pick ONE of the two options below by commenting/uncommenting. Do not enable +# both simultaneously (they would apply the same flags twice). +# +# ────────────────────────────────────────────────────────────────────── +# Option A (DISABLED) - per-component build.defines. +# Pros: zero new packages, scoped to just dracut, trivial to revert, +# lets us validate the flag list against a real build before +# committing to a distro-wide rollout. +# Cons: per-spec mechanism - not how we'd ship this distro-wide. +# +# Option B (ACTIVE) - pull in a new "azl-bootstrap-hardening" RPM that +# drops a macros.d file into the buildroot. Same flags, but delivered +# the way we'd eventually ship them for the whole distro. +# See base/comps/azl-bootstrap-hardening/. +# ────────────────────────────────────────────────────────────────────── + +[components.dracut] + +# -- Option A (DISABLED): macro overrides via build.defines ------------ +# Kept commented as a per-package escape hatch for bisecting flag changes +# without touching the distro-wide macros file. +# [components.dracut.build.defines] +# _hardened_build = "1" +# __global_compiler_flags = "-O2 -g -fstack-protector-strong -fstack-clash-protection -fPIE -D_FORTIFY_SOURCE=3" +# __global_ldflags = "-Wl,-z,relro,-z,now -Wl,-z,noexecstack -pie" + +# -- Option B (ACTIVE): macros package via BuildRequires --------------- +# Pulls in azl-bootstrap-hardening, which ships a macros.d drop-in that +# sets %_hardened_build and appends the global compiler/ld flags. Same +# delivery mechanism we want for the distro-wide rollout. +overlays = [ + { type = "spec-add-tag", tag = "BuildRequires", value = "azl-bootstrap-hardening", description = "Inject AzL stage1/2 hardening macros (PIE, RELRO, stack protector, FORTIFY) via the azl-bootstrap-hardening macros.d drop-in. Pilot for the broader azl4-bootstrap-compliance BinSkim remediation." }, +] diff --git a/docs/hardening-flags.md b/docs/hardening-flags.md new file mode 100644 index 00000000000..5a6a8604997 --- /dev/null +++ b/docs/hardening-flags.md @@ -0,0 +1,83 @@ +# Hardening Flags for Azure Linux 4.0 Builds + +## Why this matters + +Azure Linux 4.0 builds use Fedora's `redhat-rpm-config` as-is, which does not +enable `%_hardened_build` by default. As a result, BinSkim compliance scans +fail on most native packages with three rules: + +| Rule | Issue | Flag needed | +| ------ | ---------------------- | ---------------------------- | +| BA3001 | Not PIE | `-fPIE -pie` | +| BA3003 | No stack protector | `-fstack-protector-strong` | +| BA3011 | RELRO not enabled | `-Wl,-z,relro,-z,now` | + +The fix is to inject these flags through RPM macros so every spec that uses +`%configure`, `%cmake`, `%meson`, or `%make_build` picks them up automatically. +The same approach works for both stage1 and stage2. + +## The flags we want set + +``` +%_hardened_build 1 +%__global_compiler_flags -O2 -g -fstack-protector-strong -fstack-clash-protection -fPIE -D_FORTIFY_SOURCE=3 +%__global_ldflags -Wl,-z,relro,-z,now -Wl,-z,noexecstack -pie +``` + +## Option A — set macros per component + +Add the macros to a component's `[components..build.defines]` block in +its `comp.toml`. `azldev` will write a sidecar `.azl.macros` file and +add `%{load:…}` to the rendered spec. + +Example: [base/comps/dracut/dracut.comp.toml](../base/comps/dracut/dracut.comp.toml). + +**Good for**: trying flag changes on one package without affecting anything else. + +**Bad for**: distro-wide rollout — you'd repeat the same block in every +component's TOML. + +## Option B — ship the macros in an RPM + +Build a tiny noarch package (`azl-bootstrap-hardening`) that drops a +`macros.azl-bootstrap-hardening` file into `/usr/lib/rpm/macros.d/`. When +that package is installed in the buildroot, `rpm` reads the file at startup +and the macros apply to every build. + +Install it everywhere by adding it once to `chroot_setup_cmd` in each mock +template: + +| Stage | File | +| ------ | ---- | +| stage1 | [distro/mock/azl4/stage1/azurelinux-4.0.tpl](../distro/mock/azl4/stage1/azurelinux-4.0.tpl) | +| stage2 | [distro/mock/azl4/stage2/azurelinux-4.0.tpl](../distro/mock/azl4/stage2/azurelinux-4.0.tpl) | + +No spec edits required. + +Package definition: [base/comps/azl-bootstrap-hardening/](../base/comps/azl-bootstrap-hardening/). + +## Which to use + +| | Option A | Option B | +| ---------------------------- | ----------------- | ------------------ | +| Spec edits | per component | none | +| Source of truth | many TOML files | one RPM | +| Arch-conditional macros | no | yes (`%ifarch`) | +| Revert | per component | one mock line | +| Works in stage1 | yes | yes | +| Works in stage2 | yes | yes | + +**Recommendation: Option B.** Single source of truth, no per-spec churn, and +the same package can be dropped into both stage1 and stage2 buildroots. + +Keep Option A available as a way to test flag changes on one package before +updating the distro-wide macros file. + +## What this won't fix + +Some packages will still fail compliance after the flags are set globally. +These need per-spec work and aren't solved by either option: + +- Build systems that clobber `CFLAGS`/`LDFLAGS` (raw `cmake`, raw `go build`). +- Rust uses `RUSTFLAGS`, not `CFLAGS` — needs a separate macro. +- Asm-only or prebuilt-blob packages — candidates for a "known exceptions" list. diff --git a/specs/a/azl-bootstrap-hardening/azl-bootstrap-hardening.spec b/specs/a/azl-bootstrap-hardening/azl-bootstrap-hardening.spec new file mode 100644 index 00000000000..e92999c3cd8 --- /dev/null +++ b/specs/a/azl-bootstrap-hardening/azl-bootstrap-hardening.spec @@ -0,0 +1,39 @@ +# This spec file has been modified by azldev to include build configuration overlays. +# Do not edit manually; changes may be overwritten. + +Name: azl-bootstrap-hardening +Version: 1 +Release: 1%{?dist} +Summary: Stage1 BinSkim hardening macros for Azure Linux +License: MIT +URL: https://aka.ms/azurelinux +BuildArch: noarch + +Source0: macros.azl-bootstrap-hardening + +# rpm reads /usr/lib/rpm/macros.d/* at startup, so installing this drop-in +# is the only thing we need to do — no scriptlets required. +Requires: redhat-rpm-config + +%description +Layers Azure Linux stage1 compiler/linker hardening defaults on top of +Fedora's redhat-rpm-config via a /usr/lib/rpm/macros.d/ drop-in. Pilot +package used to evaluate distro-wide BinSkim remediation for the +azl4-bootstrap-compliance build target before broader rollout. + +%prep +# Nothing to unpack. + +%build +# Nothing to build. + +%install +install -d %{buildroot}%{_rpmconfigdir}/macros.d +install -m 0644 %{SOURCE0} %{buildroot}%{_rpmconfigdir}/macros.d/macros.azl-bootstrap-hardening + +%files +%{_rpmconfigdir}/macros.d/macros.azl-bootstrap-hardening + +%changelog +* Tue May 27 2026 Azure Linux Team - 1-1 +- Initial package for stage1 hardening flag rollout pilot. diff --git a/specs/a/azl-bootstrap-hardening/macros.azl-bootstrap-hardening b/specs/a/azl-bootstrap-hardening/macros.azl-bootstrap-hardening new file mode 100644 index 00000000000..0a4b6fab2ec --- /dev/null +++ b/specs/a/azl-bootstrap-hardening/macros.azl-bootstrap-hardening @@ -0,0 +1,27 @@ +# macros.azl-bootstrap-hardening +# +# Distro-wide hardening defaults for stage1 builds. Layered ON TOP of +# Fedora's redhat-rpm-config via macros.d drop-in priority — does not +# fork or replace any redhat-rpm-config file. +# +# Effect: when this package is installed in the buildroot, any spec that +# uses %configure / %cmake / %meson / %make_build / %set_build_flags +# picks up these flags. Build systems that bypass those macros and call +# the compiler directly will still need per-spec fixes. +# +# Pilot scope: dracut (see base/comps/dracut/dracut.comp.toml). +# Distro-wide rollout will inject this package into the stage1 mock +# chroot_setup_cmd once the pilot results are good. + +# Toggle Fedora's redhat-hardened-cc1 / redhat-hardened-ld spec files. +# Covers PIE, RELRO+now, stack protector, fortify on packages that +# honor Fedora's hardening hooks. +%_hardened_build 1 + +# Explicit appends for build systems that override %optflags / LDFLAGS +# but still respect %__global_compiler_flags / %__global_ldflags via +# %set_build_flags. Arch-guard CET (only meaningful on x86_64). +%__global_compiler_flags %{__global_compiler_flags} -fstack-protector-strong -fstack-clash-protection -fPIE -D_FORTIFY_SOURCE=3 %{?_cet_flag} +%__global_ldflags %{__global_ldflags} -Wl,-z,relro,-z,now -Wl,-z,noexecstack -pie + +%_cet_flag %{lua: if rpm.expand("%{_target_cpu}") == "x86_64" then print("-fcf-protection=full") end} diff --git a/specs/d/dracut/dracut.spec b/specs/d/dracut/dracut.spec index c12c660db99..9291c799aba 100644 --- a/specs/d/dracut/dracut.spec +++ b/specs/d/dracut/dracut.spec @@ -11,7 +11,7 @@ Name: dracut Version: 107 -Release: 9%{?dist} +Release: 10%{?dist} Summary: Initramfs generator using udev @@ -124,6 +124,7 @@ Requires: procps-ng Requires: libkcapi-hmaccalc +BuildRequires: azl-bootstrap-hardening %description dracut contains tools to create bootable initramfses for the Linux kernel. Unlike other implementations, dracut hard-codes as little