Hardening CFLAGS
alexhaydock opened this issue · 6 comments
Looks like your builds aren't currently passing any options to GCC but if people are using this in production directly, then it might be a good idea to throw a few optimisations in there if they offer some benefit without compromising how the builds function in any real way.
Might be worth starting a discussion about the kind of options that might be worth adding.
After some experimentation with the Nginx build options, the default CFLAGS
from the Makefile are set to:
-pipe -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g -D_GLIBCXX_USE_CXX11_ABI=0 -Wno-unused-local-typedefs -Wno-error
Some that might be worth adding, maybe:
-fPIE
- build position-independent. We can do this in the nginx build since we're building using static modules only, rather than dynamic (if we want dynamic ones we need to use-fPIC
instead).-fstack-protector-all
- I think stack protection handles overflow/underrun errors by halting execution, so I'm not sure about this one if you're targeting an enterprise scenario, but I'd probably turn it on anyway.--fstack-protector --param=ssp-buffer-size=4
- as above, but more relaxed for performance reasons (canaries only added to functions containing an array larger than 4-bytes)-Wp,-D_FORTIFY_SOURCE=2
- see Debian Wiki.
Maybe one for the linker too:
-Wl,-z,relro
- During program load, several ELF memory sections need to be written to by the linker, but can be turned read-only before turning over control to the program. (Debian wiki)
So currently I'm building with:
--with-cc-opt='-fPIE -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-all' \
--with-ld-opt='-Wl,-z,relro' \
I did briefly experiment with -O2
as a performance optimisation, but Nginx defaults to -O
and this would need to be overriden in the Makefile directly rather than with configure
options. I'm guessing that's for a reason.
But all in all, everything seems to work very nicely using these options.
Any recommendations on plumbing them in ?
I started this back before I noticed the Ubuntu script was able to use the nginx binaries directly from Canonical. Seems like the Ubuntu builds have already implemented most of these options, but it's a good idea to include them in the other scripts in case anyone is using them as a base to build a production deployment on a system that doesn't provide binaries with the right modules already integrated.
Checking the Ubuntu binary suggests they used these configure arguments:
--with-cc-opt='-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2'
--with-ld-opt='-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now'
I'll put together a PR to integrate most of the important ones into the configure section of the Raspbian script. Then if people wish to build on that, they can start from a slightly more secure base.
I'm happy to investigate the Tor build as well, but I'm wondering whether there is any particular reason for compiling Tor from source in the Raspbian example vs using the TorProject's binaries?
I'll test on Raspbian
Should work. I opted for -fstack-protector-strong
as in the Ubuntu build, instead of going for the heavyweight -fstack-protector-all
option. That should be a little kinder to the Pi.
I don't notice any real performance hit when building with -all
myself, but then again I'm not deploying anything that serves a high amount of traffic, or on hardware like the Pi.
test seems to work.