Index:
-fstack-protector to CFLAGS?The installworld stage installs libraries before executables. Given that SSP symbols are provided by libc, when the latter will be overritten, all binaries which require those symbols directly or indirectly through another shared library won't work any more. Consequently installworld will break and you won't be able to run even ls(1).
The trick is to set LD_PRELOAD to /lib/libssp.so.1 in your environnement before running installworld.
First, you have to revert the patch:
# cd /usr/src # patch -R -p0 < fbsd6-ssp-propolice.patch # patch -R -p0 < fbsd6-ssp-glue.patch
Then you can buildworld as usual. Before running installworld stage, set LD_PRELOAD to /lib/libssp.so.1 in your environnement:
# make buildworld # env LD_PRELOAD=/lib/libssp.so.1 make installworld
You will then have to remove these files/links manually:
# chflags 0 /lib/libssp.so.1 # rm /lib/libssp.so.1 # rm /usr/lib/libssp.a # rm /usr/lib/libssp.so # rm /usr/lib/libssp_p.a # rm /usr/lib/libssp_pic.a # rm /usr/share/mk/bsd.ssp.mk
Because I was simpler for me to do so and I found no good reason where an attacker would want to exploit a stack-based buffer overflow so early, before the kernel has even booted.
Libssp's constructor __guard_setup() has to fill the canary with a random value and therefore is called very early in the process execution. It initially used the open(2) system call on random(4) but the latter has not been planned to be called before the threading library is fully initialized. It leads to a SIGSEGV because of a NULL pointer dereference.
One way would be to turn open(2) to be callable that early, but I think the authors should have had good reasons to do so and changing the open(2) wrapper in both libpthread and libthr might not be worth only SSP initialization purpose.
Therefore I have proceeded like OpenBSD, using the kern.arandom sysctl.
You have to check for its required symbols, therefore you won't be able to check this against stripped objects. For dynamically linked objects:
# nm -D /bin/ls | grep __stack_smash_handler
U __stack_smash_handler
# nm -D /lib/libz.so.* | grep __stack_smash_handler
U __stack_smash_handler
# nm -D /bin/test | grep __stack_smash_handler
#
As you can see, test(1) is not protected by ProPolice, probably because the compile found no buffer to protect. For statically linked objects:
# nm /usr/lib/libz.a | grep __stack_smash_handler
U __stack_smash_handler
There are several reasons:
This patch creates a few files from scratch. This means that when you upgrade your sources, they won't be touched at all. Furthermore, if you look at the patch you will see these files are not provided with any context which can be checked by patch(1). Thus the content of the file will be simply inserted at line 0, no matter how much times you apply the patch, leading to insert the content multiple times:
% RCS file: lib/libssp/ssp.c % diff -N lib/libssp/ssp.c % --- /dev/null 1 Jan 1970 00:00:00 -0000 % +++ lib/libssp/ssp.c % @@ -0,0 +1,104 @@
The solution to this is to revert the patch before upgrading your source:
# patch -R -p0 < fbsd7-ssp-propolice.patch # patch -R -p0 < fbsd7-ssp-glue.patch
In case you have applied the patch more than once, you will have to remove the files manually or remove your entire source tree and before fetching it back.
-fstack-protector to CFLAGS?Some parts of the world, such as build tools, cross tools or src/sys/boot/, must be built without stack-smashing protection for various reasons*.
make(1) expands a variable only when they it is referenced. Therefore I introduced the SSP_CFLAGS variable which is added to the content of the CFLAGS variable, in order to hold -fstack-protector. This indirection allows a library or a program which doesn't want to be compiled with stack protector to empty SSP_CFLAGS.
I could have used $(CFLAGS:N-fstack-protector), but this wouldn't have worked if CFLAGS was assigned on the command-line, since those variables are read-only. I prefered to not use this at all to prevent breaking POLA.
* Build tools and cross tools do not need to be protected. Furthermore, trying to compile them with -fstack-protector would break when the current world is not SSP-ready, because the installed GCC will simply not know this flag. Boot utils living in src/sys/boot/ aren't very likey to be an attack vector, so we can safely avoid protecting them. These programs are linked statically and not linked against libc, so this would require to add a hack to provide them with SSP symbols.
This is out of my responsability. Some ports are known to not honor FreeBSD's CFLAGS and consequently won't be compiled with SSP flags.
If you really need one of your port to be SSP'ed, you will have to write a patch for this port. I think Gábor Kövesdán will be glad to receive some help. This task is indeed part of is Google SoC project (Make ports respect CC and CFLAGS ).
Your libc has probably been recompiled without SSP symbols. Fortunately libssp is provided so you can use LD_PRELOAD to workaround this and get the required symbols until you get back to a stable system:
# LD_PRELOAD=/usr/lib/libssp.so
Your best bet is to first go back to a non-patched RELENG_6, as explained on this FAQ. Then upgrade to RELENG_7 or CURRENT.
Here is a list built from my own experience but please let me know if you stumble of some other ports in this case: