Bug#673112: lintian: hardening-no-stackprotector check has many false positives
On 2012-05-22 13:05, Niels Thykier wrote:
> [...]
>
> Turns out hardening-check has a verbose flag that makes it print the
> affected functions - testing amarok (testing i386) I got[1]. Looks like
> memcpy is the primary source of false-positives (for amarok).
>
> If it turns out that memcpy is (in general) the primary source of these
> false-positives, perhaps it would be better to skip that particular
> function than disable the entire check.
>
> ~Niels
>
> [1]
> [...]
>
>
>
Okay, final "spam" for now.
I think it would be a very good idea to drop at least memcpy from the
hardening-check because GCC 4.7 (at -O2 or higher), GCC may replace
strcpy and other functions with memcpy[1].
I have tested a little code snippet[2] with gcc-4.7 and it indeed it
replaces strcpy with memcpy at -O2. Also it never uses the fortified
variant of strcpy/memcpy (not even at -O0) in this "trivial case".
So for -O0 binaries we would still get false-positives in this case (and
binaries compiled with < 4.7), but we would presumably avoid a lot of
false-positiives for binaries compiled by gcc-4.7 -O2 in this way.
~Niels
[1] http://gcc.gnu.org/gcc-4.7/changes.html
"""
A string length optimization pass has been added. It attempts to track
string lengths and optimize various standard C string functions like
strlen, strchr, strcpy, strcat, stpcpy and their _FORTIFY_SOURCE
counterparts into faster alternatives. This pass is enabled by default
at -O2 or above, unless optimizing for size, and can be disabled by the
-fno-optimize-strlen option. The pass can e.g. optimize
char *bar (const char *a)
{
size_t l = strlen (a) + 2;
char *p = malloc (l); if (p == NULL) return p;
strcpy (p, a); strcat (p, "/"); return p;
}
into:
char *bar (const char *a)
{
size_t tmp = strlen (a);
char *p = malloc (tmp + 2); if (p == NULL) return p;
memcpy (p, a, tmp); memcpy (p + tmp, "/", 2); return p;
}
[...]
"""
[2] // Poor man's strdup
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
const char *s = argv[0];
size_t l = strlen(s);
char *cpy = malloc (l + 1);
if (!cpy)
return 1;
strcpy(cpy, s);
cpy[0] = 'b';
printf("%s\n", cpy);
return 0;
}
Reply to: