Skip to content

Commit 0c6ce12

Browse files
committed
Add CMake based compiler hardening guide
1 parent b684602 commit 0c6ce12

File tree

6 files changed

+146
-0
lines changed

6 files changed

+146
-0
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
cmake_minimum_required(VERSION 3.27 FATAL_ERROR)
2+
project(demo LANGUAGES C)
3+
4+
set(CMAKE_C_STANDARD 23)
5+
set(CMAKE_C_STANDARD_REQUIRED ON)
6+
7+
#
8+
# compiler hardening
9+
#
10+
11+
if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 14.0.0)
12+
message(FATAL_ERROR "GCC is outdated: ${CMAKE_C_COMPILER_VERSION}")
13+
endif()
14+
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 16.0.0)
15+
message(FATAL_ERROR "Clang is outdated: ${CMAKE_C_COMPILER_VERSION}")
16+
endif()
17+
18+
add_compile_options(
19+
-O2
20+
-Wall
21+
-Wextra
22+
-Wformat
23+
-Wformat=2
24+
-Wconversion
25+
-Wsign-conversion
26+
-Wimplicit-fallthrough
27+
-Werror=format-security
28+
# more portable and explicit than -fhardened
29+
-U_FORTIFY_SOURCE
30+
-D_FORTIFY_SOURCE=3
31+
-D_GLIBCXX_ASSERTIONS
32+
-fstrict-flex-arrays=3
33+
-fstack-protector-strong
34+
# deprecated c calls
35+
-Werror=implicit
36+
-Werror=incompatible-pointer-types
37+
-Werror=int-conversion
38+
# multithreading with pthreads
39+
-fexceptions
40+
# for shared libraries use `-fPIC`
41+
-fPIE
42+
)
43+
44+
# build mode specific
45+
if(CMAKE_BUILD_TYPE STREQUAL "Release")
46+
add_compile_options(
47+
-fno-delete-null-pointer-checks -fno-strict-overflow -fno-strict-aliasing -ftrivial-auto-var-init=zero
48+
)
49+
else()
50+
add_compile_options(-Werror)
51+
endif()
52+
53+
# os specific
54+
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
55+
add_compile_options(-fstack-clash-protection)
56+
add_link_options(
57+
-pie
58+
-Wl,-z,nodlopen
59+
-Wl,-z,noexecstack
60+
-Wl,-z,relro
61+
-Wl,-z,now
62+
-Wl,--as-needed
63+
-Wl,--no-copy-dt-needed-entries
64+
)
65+
endif()
66+
67+
# compiler specific
68+
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
69+
# from gcc-15 add `-fzero-init-padding-bits=all`
70+
add_compile_options(-Wtrampolines -Wbidi-chars=any)
71+
endif()
72+
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
73+
# nop
74+
endif()
75+
76+
# architecture specific
77+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64|i686|i386")
78+
add_compile_options(-fcf-protection=full)
79+
endif()
80+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64|ARM64")
81+
add_compile_options(-mbranch-protection=standard)
82+
endif()
83+
84+
#
85+
# sources
86+
#
87+
88+
add_executable(demo demo.c)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
FROM --platform=linux/amd64 ubuntu:24.04
2+
3+
RUN apt-get update && apt-get install -y --no-install-recommends \
4+
gcc-14 g++-14 \
5+
clang-19 \
6+
cmake make \
7+
valgrind \
8+
&& update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 100 \
9+
&& update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 100 \
10+
&& update-alternatives --install /usr/bin/clang clang /usr/bin/clang-19 100 \
11+
&& rm -rf /var/lib/apt/lists/*
12+
13+
WORKDIR /workspace
14+
COPY . /workspace
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
DOCKER_RUN = docker run --rm -v $(PWD):/workspace main sh -c
2+
3+
.PHONY: build-image
4+
build-image:
5+
docker build -t main .
6+
7+
.PHONY: run-gcc
8+
run-gcc: build-image
9+
$(DOCKER_RUN) "mkdir -p /tmp/gcc-build && cd /tmp/gcc-build && cmake -DCMAKE_C_COMPILER=gcc /workspace && make && ./demo"
10+
11+
.PHONY: run-clang
12+
run-clang: build-image
13+
$(DOCKER_RUN) "mkdir -p /tmp/clang-build && cd /tmp/clang-build && cmake -DCMAKE_C_COMPILER=clang /workspace && make && ./demo"
14+
15+
.PHONY: clean
16+
clean:
17+
docker rmi main
File renamed without changes.
File renamed without changes.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Test C/C++ hardening flags
2+
3+
// Copyright Open Source Security Foundation (OpenSSF) and its contributors
4+
// SPDX-License-Identifier: Apache-2.0 OR MIT
5+
6+
#include <stdio.h>
7+
8+
// Linux 5.10 solution:
9+
#if __has_attribute(__fallthrough__)
10+
# define fallthrough __attribute__((__fallthrough__))
11+
#else
12+
# define fallthrough do {} while (0) /* fallthrough */
13+
#endif
14+
15+
int main(void) {
16+
int c = 0;
17+
switch (c) {
18+
case 1:
19+
printf("Hello\n");
20+
fallthrough;
21+
case 0:
22+
printf("Goodbye\n");
23+
fallthrough;
24+
default:
25+
printf("Default\n");
26+
}
27+
}

0 commit comments

Comments
 (0)