-
Bug
-
Resolution: Unresolved
-
Blocker
-
None
-
CentOS Stream 10
-
None
-
None
-
Critical
-
rhel-container-tools
-
None
-
None
-
None
-
None
-
None
-
x86_64
-
None
What were you trying to do that didn't work?
Auditing container runtime RPMs for binary hardening compliance. The crun binary has PIE and full RELRO but is missing stack canary protection and FORTIFY_SOURCE because the spec file uses bare ./configure instead of the RPM %configure macro, which skips injection of %{optflags} and %{build_ldflags}{}.
What is the impact of this issue to you?
crun is the OCI container runtime — it is the binary that creates and enforces the container isolation boundary on every podman and cri-o invocation. It runs as root and performs the most security-critical operations in the container stack:
- Creates Linux namespaces (PID, network, mount, user)
- Configures cgroups for resource isolation
- Applies seccomp syscall filters
- Drops capabilities
- Calls pivot_root to isolate the filesystem
- Parses OCI runtime spec JSON, which is influenced by container image metadata — meaning attacker-controlled input reaches crun before container isolation is established
Without stack protector, a stack-based buffer overflow in crun's JSON parsing, namespace setup, or cgroup configuration code would not be detected at runtime. Without FORTIFY_SOURCE, buffer operations that could be bounds-checked at compile time are not. This is the container sandbox boundary — a compromise of crun means full host access from a malicious container image.
The root cause is that the spec file's %build section uses:
./configure --disable-silent-rules %{krun_opts} %{wasmedge_opts} %{yajl_opts}
The RPM %configure macro automatically injects CFLAGS="%{optflags}" and LDFLAGS="%{build_ldflags}", which include -fstack-protector-strong, -D_FORTIFY_SOURCE=2, and other standard RHEL hardening flags. Using bare ./configure bypasses all of this.
Please provide the package NVR for which the bug is seen:
crun-1.26-1.el10.x86_64
How reproducible is this bug?:
Always — the spec file uses ./configure instead of %configure.
Steps to reproduce
- rpm2cpio crun-1.26-1.el10.x86_64.rpm | cpio -i --to-stdout ./usr/bin/crun 2>/dev/null > /tmp/crun
- readelf -h /tmp/crun | grep Type — shows DYN (PIE present, correct)
- readelf -d /tmp/crun | grep BIND_NOW — present (RELRO correct)
- readelf -s /tmp/crun | grep stack_chk — no output (no stack canary)
- readelf -s /tmp/crun | grep FORTIFY — no output (no FORTIFY_SOURCE)
- Review spec file at https://gitlab.com/redhat/centos-stream/rpms/crun/-/blob/c10s/crun.spec — the %build section uses ./configure instead of %configure
Expected results
The spec file should use the RPM %configure macro, or explicitly pass hardening flags:
{{# Option 1: Use %configure macro (preferred)
%configure --disable-silent-rules %{krun_opts} %{wasmedge_opts} %{yajl_opts}
- Option 2: Explicit flags
CFLAGS="%{optflags}" LDFLAGS="%{build_ldflags}" ./configure --disable-silent-rules %{krun_opts} %{wasmedge_opts} %{yajl_opts}}}
Either approach would add -fstack-protector-strong, -D_FORTIFY_SOURCE=2, and other standard RHEL hardening flags to the container runtime binary.Actual results
The spec file uses bare ./configure which does not inject RPM hardening flags. The resulting /usr/bin/crun binary has PIE and full RELRO but no stack canary and no FORTIFY_SOURCE. This is the binary that creates and enforces the container isolation boundary on every RHEL system using podman or cri-o.