1#!/usr/bin/make -f
2#
3# Copyright (C) 2009-2014 Kees Cook <kees@debian.org>
4# License: GPLv2 or newer
5#
6# This file is intended to be included in a Debian rules file so that the
7# the calculated HARDENING_CFLAGS and HARDENING_LDFLAGS from this makefile
8# can by used in the package's CFLAGS (and/or CXXFLAGS) and LDFLAGS to
9# harden the security of a package's resulting binaries. For example:
10#
11#   include /usr/share/hardening-includes/hardening.make
12#   CFLAGS += $(HARDENING_CFLAGS)
13#   LDFLAGS += $(HARDENING_LDFLAGS)
14#
15# and if you need it for C++ compilations:
16#
17#   CXXFLAGS += $(HARDENING_CFLAGS)
18#
19#
20# By default, all hardening options that are valid for a given architecture
21# are enabled. The following can be set before or after including this
22# makefile:
23#   To disable all hardening:        DEB_BUILD_HARDENING:=0
24#   To disable PIE:                  DEB_BUILD_HARDENING_PIE:=0
25#   To disable stack protector:      DEB_BUILD_HARDENING_STACKPROTECTOR:=0
26#   To disable Fortify Source:       DEB_BUILD_HARDENING_FORTIFY:=0
27#   To disable format string checks: DEB_BUILD_HARDENING_FORMAT:=0
28#   To disable readonly relocations: DEB_BUILD_HARDENING_RELRO:=0
29#   To disable BIND_NOW:             DEB_BUILD_HARDENING_BINDNOW:=0
30#
31# For more details, see https://wiki.debian.org/Hardening
32#
33# Thanks to Ryan Niebur for help with the Makefile magicks.
34#
35# -- Kees Cook <kees@debian.org>
36
37DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH 2>/dev/null)
38DEB_HOST_ARCH_OS ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_OS 2>/dev/null)
39
40DEB_BUILD_HARDENING ?= 1
41
42ifneq (,$(filter $(DEB_HOST_ARCH_OS), linux knetbsd hurd ))
43  # PIE enabled only on linux, knetbsd, and hurd (bugs 430455 and 586215)
44  ifeq (,$(filter $(DEB_HOST_ARCH), hppa m68k mips mipsel avr32 ))
45    # disabled on hppa (bug number needed)
46    # disabled on m68k (bug 451192)
47    # disabled on mips/mipsel (toolchain bug 532821)
48    # disabled on avr32 (bug 574716)
49    DEB_BUILD_HARDENING_PIE ?= 1
50  endif
51endif
52DEB_BUILD_HARDENING_PIE ?= 0
53
54ifneq (,$(filter $(DEB_HOST_ARCH), ia64 alpha hppa arm))
55  # Stack protector disabled on ia64, alpha, hppa.
56  #   "warning: -fstack-protector not supported for this target"
57  # Stack protector disabled on arm (ok on armel, armhf).
58  #   compiler supports it incorrectly (leads to SEGV)
59  DEB_BUILD_HARDENING_STACKPROTECTOR ?= 0
60endif
61DEB_BUILD_HARDENING_STACKPROTECTOR ?= 1
62
63ifneq (,$(filter $(DEB_HOST_ARCH), ia64 hppa avr32 ))
64  DEB_BUILD_HARDENING_RELRO ?= 0
65endif
66DEB_BUILD_HARDENING_RELRO ?= 1
67
68DEB_BUILD_HARDENING_FORTIFY ?= 1
69DEB_BUILD_HARDENING_FORMAT ?= 1
70DEB_BUILD_HARDENING_BINDNOW ?= 1
71
72_HARDENED_PIE_CFLAGS  := -fPIE
73_HARDENED_PIE_LDFLAGS := -fPIE -pie
74
75_HARDENED_STACKPROTECTOR_CFLAGS := -fstack-protector-strong
76
77# Fortify Source requires that -O1 or higher is used, but that should be
78# handled outside of this include file.
79_HARDENED_FORTIFY_CFLAGS  := -D_FORTIFY_SOURCE=2
80
81_HARDENED_FORMAT_CFLAGS   := -Wformat -Wformat-security -Werror=format-security
82
83_HARDENED_RELRO_LDFLAGS   := -Wl,-z,relro
84
85_HARDENED_BINDNOW_LDFLAGS := -Wl,-z,now
86
87_hardening_enabled = $(if $(filter $(DEB_BUILD_HARDENING), yes 1 on true),\
88$(if $(filter $(1), yes 1 on true),$(2),),)
89
90HARDENING_CFLAGS ?= \
91$(call _hardening_enabled,$(DEB_BUILD_HARDENING_PIE),$(_HARDENED_PIE_CFLAGS)) \
92$(call _hardening_enabled,$(DEB_BUILD_HARDENING_STACKPROTECTOR),$(_HARDENED_STACKPROTECTOR_CFLAGS)) \
93$(call _hardening_enabled,$(DEB_BUILD_HARDENING_FORTIFY),$(_HARDENED_FORTIFY_CFLAGS)) \
94$(call _hardening_enabled,$(DEB_BUILD_HARDENING_FORMAT),$(_HARDENED_FORMAT_CFLAGS)) \
95
96HARDENING_LDFLAGS ?= \
97$(call _hardening_enabled,$(DEB_BUILD_HARDENING_PIE),$(_HARDENED_PIE_LDFLAGS)) \
98$(call _hardening_enabled,$(DEB_BUILD_HARDENING_RELRO),$(_HARDENED_RELRO_LDFLAGS)) \
99$(call _hardening_enabled,$(DEB_BUILD_HARDENING_BINDNOW),$(_HARDENED_BINDNOW_LDFLAGS)) \
100
101# Utility macros designed to allow package maintainer to force a given
102# hardening feature off in certain areas of a build without disabling
103# the option for the entire build. For example:
104#   CFLAGS += $(HARDENING_CFLAGS)
105#   monkey.o: monkey.c
106#       $(CC) $(CFLAGS) $(HARDENING_DISABLE_STACKPROTECTOR_CFLAGS) $< -o $@
107HARDENING_DISABLE_STACKPROTECTOR_CFLAGS:=-fno-stack-protector
108HARDENING_DISABLE_FORTIFY_CFLAGS:=-U_FORTIFY_SOURCE
109HARDENING_DISABLE_FORMAT_CFLAGS:=-Wno-format-security
110HARDENING_DISABLE_RELRO_LDFLAGS:=-Wl,-z,norelro
111HARDENING_DISABLE_BINDNOW_LDFLAGS:=-Wl,-z,lazy
112# Note: GCC does not have a way to just turn off pie (there is no "-nopie")
113# so if PIE needs to be disabled for a specific target, the CFLAGS and LDFLAGS
114# need to be filtered. For example:
115#   monkey: monkey.c
116#       $(CC) $(filter-out $(HARDENING_DISABLE_PIE_CFLAGS_FILTER),$(CFLAGS)) \
117#             $(filter-out $(HARDENING_DISABLE_PIE_LDFLAGS_FILTER),$(LDFLAGS)) \
118#             $< -o $@
119#
120# Note: when building shared libraries, or with some build frameworks (e.g.
121# cmake) that pass "-fPIC" to everything, the "-fPIE" option must be filtered
122# out to avoid building shared objects that need PIC but end up only with PIE.
123# This is usually indicated by errors at link time that look like this:
124#  relocation R_X86_64_PC32 against symbol `foo' can not be used when making a shared object; recompile with -fPIC
125# In these cases, the CFLAGS can be filtered to exclude "-fPIE" until this
126# is fixed in gcc correctly. For example, on one target:
127#   monkey.o: monkey.c
128#       $(CC) $(filter-out $(HARDENING_DISABLE_PIE_CFLAGS_FILTER),$(CFLAGS)) \
129#             $< -c -o $@
130# In cases where mixed shared objects and executable objects are being built,
131# "-fPIC" needs to actually replace "-fPIE", since gcc won't distinguish
132# between them yet. For example:
133#   export CFLAGS=$(shell dpkg-buildflags --get CFLAGS)
134#   CFLAGS += $(HARDENING_CFLAGS_PIC) \
135#             $(filter-out $(HARDENING_DISABLE_PIE_CFLAGS_FILTER),$(HARDENING_CFLAGS))
136#
137HARDENING_DISABLE_PIE_CFLAGS_FILTER:=$(_HARDENED_PIE_CFLAGS)
138HARDENING_DISABLE_PIE_LDFLAGS_FILTER:=$(_HARDENED_PIE_LDFLAGS)
139HARDENING_CFLAGS_PIC:=-fPIC
140