Hi.  I've noticed a few things about the new stack protector
implementation in gcc-4.1, which are different from the Etoh's IBM
patch that we've been using on Gentoo in the gcc-3 series for a good
while now.


Looking back through the list archives, I see this has been discussed
before, but not really satisfactorily for all concerned.  I understand
the idea that -fno-stack-protector, -fstack-protector and
-fstack-protector-all in the new implementation are essentially
controlling a three-state concept of stack protection.  However things
weren't this way in the Etoh's patch, so this can and will cause
confusion as people transition from gcc-3 to gcc-4.


The gcc-3 semantics are:

-fstack-protector:
Switch on heuristically-applied stack protection.
#define __SSP__=1

-fstack-protector-all:
Switch on stack protection for all functions.
#define __SSP__=1
#define __SSP_ALL__=2

-fno-stack-protector:
Switch off -fstack-protector
Unless -fstack-protector-all is specified, no defines.

-fno-stack-protector-all:
Switch off -fstack-protector-all
Unless -fstack-protector is specified, no defines.


The current gcc-4.1 semantics are:

-fstack-protector:
Switch on heuristically-applied stack protection.
#define __SSP__=1

-fstack-protector-all:
Switch on stack protection for all functions.
#define __SSP_ALL__=2

-fno-stack-protector:
Switch off stack protection


An example where this matters: with gcc-3, we can add
'-fno-stack-protector-all' to CFLAGS unconditionally if we want to
prevent stack protection being applied to all functions, but leave
heuristic stack protection alone according to the user's wishes.

With the gcc-4.1 semantics, this can't be done so simply; adding
'-fstack-protector' would have the side-effect of switching it on
heuristically if it wasn't already on, and adding
'-fno-stack-protector' would have the side-effect of switching it off
completely even if heuristic stack protection was on previously.

We can deal with this, of course, although it does make things a little
more involved.


Also of some concern is the setting of the __SSP__ and __SSP_ALL__
macros, which again has changed from the gcc-3 implementation to that in
gcc-4.1.  In gcc-3 it was sufficient to test __SSP__ to discover if any
stack protection is on, whereas in gcc-4 it's necessary to test both
macros:

#if defined(__SSP__) || defined(__SSP_ALL__)

which is not very pretty.


That's the situation as it stands today.  Two incompatible
implementations, neither of which are completely tidy. So here are some
ideas I'd like to suggest for discussion, assuming that maintaining
100% backwards compatibility with Etoh's gcc-3 patches is not a goal:


1) Define __SSP__ as 2 when stack protection is applied to all
functions.

This would make it cleaner to detect SSP support via tests like:

#if __SSP__>0
blah
#endif

I see no good reason to have two different macros, when the behaviour
is intended to be three-state.

I don't know if anyone actually uses __SSP_ALL__ - it might be
interesting to find out.  We (Gentoo) used to, but we don't any more.
It could be dropped, although leaving it present won't hurt anyone.


2) Instead of the three switches, have '-fstack-protector=N' where N is
0, 1 or 2 for no protection, heuristic protection and full protection
respectively, and where '-fstack-protector' is equivalent to
'-fstack-protector=1'.

It would be obvious from this what the gcc-4.1 behaviour is (i.e. one
three-level option rather than two binary options), and that the
behaviour is different from gcc-3.

There are a few '-ffoo=N' options already, however they generally use N
to imply a count of some kind which is not the case here although I'm
not particularly concerned about that.  An alternative would be the '-O'
style; i.e. have -fstack-protector0, -fstack-protector1 and
-fstack-protector2, with -fstack-protector equivalent to
-fstack-protector1.  However other '-ffooN' switches are usually
separate binary switches so I think I prefer the '-fstack-protector=N'
approach.


3) Rename stack-protector as stack-protection and __SSP__ as __SPN__, to
even more clearly differentiate gcc-4.1 support from the gcc-3 patches.

Probably more trouble than it's worth; differentiating can always be
done by checking the major version as in "#if __GNUC__>3", unless the
gcc-3 patch is ported to gcc-4 which I guess is unlikely.


Shoot away,
Kev.

Reply via email to