rm strcpy
There are all sort of clever (and complicated) solutions to this, that involve randomising stack addresses, and putting in canaries, or using NX (NoExec) areas of memory, either hardware, or emulated in software (with a corresponding performance hit).
There is a much simpler answer though - strcpy has a replacement - strncpy. The n in the middle means the number of characters that can be copied in. Obviously, you'll have to know how big the thing is first, but that shouldn't be too hard.
So why, in this age of enlightenment, in 2007, does strcpy still exist?
Because people can't be bothered to change.
So why don't we do the right thing, and give people a definite nudge away from strcpy.
Let's just remove strcpy from glibc.
Of course, there's lots of software that uses strcpy, and this would all break if glibc was upgraded. There are three solutions to this.
1. Don't update glibc if you have software that is old, closed source, or that you can't update.
2. If you have to update glibc, first update the source code to use strncpy. (This is easy for Open Source programs, but hard for old, closed source apps.)
3. If you really, really must have strcpy, we can leave strcpy in glibc, and disable it by default, but have a compile-time flag for glibc. --build-with-stupid-insecure-strcpy-because-im-too-lazy-to-change.
If you want to make an tasty, more-secure Linux omelette, you have to temporarily break a few nastily coded eggs.