Translation(s): none


What is all this about?

Build flags are the options passed to the compiler when building software written in languages such as C, C++, Objective-C, Objective-C++, D, Fortran or assembler. They control aspects such as how the compiler optimises code and whether some issues are treated as errors or warnings. Other languages such as Java, pure Python, pure Perl or shell have no such concept and packages for those languages can ignore this topic.

dpkg-buildflags controls which build flags are used. It allows:

dpkg-buildflags also honours DEB_BUILD_OPTIONS=noopt (policy 4.9.1), which lets you build a package with a mimimum of optimisation. For example this will enable -O0 to disable optimisation. Not every package implements this correctly.

As well as setting the flags in your debian/rules file you also need to ensure that the build system uses the flags. [how?]

Default build flags

The default build flags can be seen by running

dpkg-buildflags --dump

Since Debian 7 ("wheezy") this includes

These hardening features are explained in more depth here.

Additionally there are two other build flags which are not enabled by default (because they can cause issues):

It is recommended to test whether these two additional build flags work with your package and enable them if everything works fine. To can enable them, add:

export DEB_BUILD_MAINT_OPTIONS = hardening=+all

to your debian/rules file.

Enabling build flags

Modern debhelper-based packaging

Packages using debhelper version 9 or later do not need to do anything to use the default build flags. You can add additional flags by setting the DEB_CFLAGS_MAINT_APPEND and DEB_LDFLAGS_MAINT_APPEND variables, or enable the additional hardening flags by setting DEB_BUILD_MAINT_OPTIONS:

## Add this to the top of debian/rules
# export DEB_BUILD_MAINT_OPTIONS = hardening=+all # recommended
export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic
export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed # see below

(Note that the DEB_LDFLAGS_MAINT_APPEND is just an example: gcc already passes this -Wl,--as-needed to the linker by default since Debian 11 (bullseye)

If you really want to overwrite the defaults you can use *_SET instead of *_APPEND but this is not usually a good idea.

There is no need to export variables such as CFLAGS or LDFLAGS as they are automatically passed to the dh_auto_* programs as needed.

Older debhelper, or hand-written packaging

If you use dh(1) version 8 or earlier you needed to include buildflags.mk and call dpkg-buildflags manually. You will need the following at the top of debian/rules.

DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/buildflags.mk

The *_APPEND variables also work here.

To ensure the build system uses the buildflags you will need:

override_dh_auto_configure:
       dh_auto_configure -- $(shell dpkg-buildflags --export=configure)

with debhelper. For hand-written calls you will need something like:

../configure --prefix=/usr $(shell dpkg-buildflags --export=configure) 

If your build system reads the values from standard environment variables like CFLAGS, CXXFLAGS, CPPFLAGS or LDFLAGS, you often need to export these (including buildflags.mk should do this for you).

cdbs

If your package uses cdbs you will usually only need to verify whether the upstream build system properly uses the environment variables (bug 651964)

cdbs supports DEB_*_MAINT_APPEND and DEB_BUILD_MAINT_OPTIONS - just make sure to declare them before including CDBS snippets.

Handling dpkg-buildflags in the upstream build system

To fully support all hardened build flags in your upstream build system, please ensure that the following environment variables are supported:

Build systems based on autotools

If your build system is based on autotools it usually requires no further modifications. It might happen that some variables are hard-coded in one of the Makefile.in files (see e.g., bug 655870), which might mean the variables passed by the packaging are not honored.

Handwritten Makefiles

If your package uses a home-grown build system you need to ensure it supports the above-mentioned variables. If not, you can patch it to do so, or add the dpkg-buildflags calls as part of your Debian-specific modifications.

For example, many home-grown Makefiles already support CFLAGS and LDFLAGS but not CPPFLAGS. In most cases you can simply append CPPFLAGS to CFLAGS, e.g.

CFLAGS = `dpkg-buildflags --get CFLAGS`
CFLAGS += `dpkg-buildflags --get CPPFLAGS`

Build systems for Perl modules

debhelper passes the appropriate build flags to ExtUtils::MakeMaker and ExtUtils::CBuilder, so most Perl modules should receive hardened build flags (assuming you use debhelper level 9 or later). Note that the dh_auto* minimal rules files need to be used to make use of this.

See more discussion at bug 662666.

Build systems using cmake

cmake doesn't follow CPPFLAGS. A fix was rejected by upstream (bug 653916). As a workaround appending CPPFLAGS to CFLAGS and CXXFLAGS should work in most cases (debhelper and cdbs handle this automatically)

Testing your packages after modifying buildflags

Debian provides several ways to test that binaries were built with expected build flags:

$ hardening-check /usr/bin/emacs23
/usr/bin/emacs23:
 Position Independent Executable: no, normal executable!
 Stack protected: yes
 Fortify Source functions: yes (some protected functions found)
 Read-only relocations: yes
 Immediate binding: no not found!

In some cases, "Stack protected" and "Fortify Source functions" emit false positives, see hardening-check's manpage (?DebMan:hardening-check for more information.

If a package has enabled all flags, the output should look like this:

$ hardening-check /usr/sbin/sshd
/usr/sbin/sshd:
 Position Independent Executable: yes
 Stack protected: yes
 Fortify Source functions: yes (some protected functions found)
 Read-only relocations: yes
 Immediate binding: yes

* the blhc package checks the build logs for missing hardening flags. It can be used on build logs created by dpkg-buildpackage or sbuild.

Example usage:

$ blhc /path/to/log/file.build

Common questions / problems

My package needs to build with optimisation flags other than -O2, e.g. -Os

You can add the following to your rules

DEB_CFLAGS_MAINT_APPEND=-Os

How can I set custom flags?

To set additional flags, e.g. -Wall, add them to DEB_*_MAINT_APPEND variables (see above). Do not use DEB_*_MAINT_SET as it overwrites the default hardening flags. DEB_*_APPEND (without the _MAINT) is not for debian/rules, always use *_MAINT_*.

Do not use something like export LDFLAGS += -Wl,--as-needed because the export will overwrite the default LDFLAGS hardening flags.

What problem does this solve?

dpkg-buildflags allows Debian to be rebuilt with modified build flags and is useful to spot long-standing bugs in your packages, see this blog posting on Planet Debian for an example.

My package is (partly) written in OCaml

The OCaml runtime itself must be hardened first. For the time being, do nothing (especially do not override Lintian tags): see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=702349#19

What do the flags do?

See Hardening.

Historical information

How was this introduced to Debian?

Adding flags was a release goal for Wheezy. Many of the bugs had patches attached.

How did it work in Debian Squeeze?

squeeze-backports included a backported packages, such as [which?] version 1.16.1.1.

Additionally, dpkg-buildflags already existed in plain Squeeze (emitting only flags without any hardening):

$ dpkg-buildflags --get CFLAGS
-g -O2
$ dpkg-buildflags --get CPPFLAGS

$ dpkg-buildflags --get LDFLAGS

$ dpkg-buildflags --get CXXFLAGS
-g -O2

Most of the convenience functions (/usr/share/dpkg/buildflags.mk and dpkg-buildflags --export=configure) did not exist, so flags had to be enabled by hand with, eg:

CFLAGS:=$(shell dpkg-buildflags --get CFLAGS)
CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS)
LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS)

My package already uses hardening-wrapper or hardening-includes. Should I switch to dpkg-buildflags?

Yes. These packages have now been removed from unstable for some years. You should use dpkg-buildflags instead, since it's a more generalised solution to the problem and is also useful beyond security hardening.


CategoryPackaging