For discussion of Alpine Linux development and developer support

1

[alpine-devel] fortify-headers needs replacement

alpine-mips-patches
Details
Message ID
<1394950117.20190225162429@mobile-stream.com>
Sender timestamp
1551101069
DKIM signature
missing
Download raw message
(this e-mail is a resend triggered by the aports commit 228579f6c7663dc4107b1b418367e968513277f9)

This is some dumb program:

#include <string.h>
int main(int argc, char **argv)
{
        int x;
        memcpy(&x, &argc, sizeof x);
        return x;
}

This is what it turns into when compiled with "gcc -Os -fomit-frame-pointer" on edge (or 3.8.1):

0000000000001068 <main>:
    1068:       48 83 ec 28             sub    $0x28,%rsp
    106c:       89 7c 24 0c             mov    %edi,0xc(%rsp)
    1070:       48 8d 7c 24 14          lea    0x14(%rsp),%rdi
    1075:       48 8d 74 24 0c          lea    0xc(%rsp),%rsi
    107a:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
    1081:       00 00 
    1083:       48 89 44 24 18          mov    %rax,0x18(%rsp)
    1088:       31 c0                   xor    %eax,%eax
    108a:       48 8d 47 04             lea    0x4(%rdi),%rax
    108e:       48 39 c6                cmp    %rax,%rsi
    1091:       73 05                   jae    1098 <main+0x30>
    1093:       48 39 f7                cmp    %rsi,%rdi
    1096:       72 0e                   jb     10a6 <main+0x3e>
    1098:       48 8d 46 04             lea    0x4(%rsi),%rax
    109c:       48 39 c7                cmp    %rax,%rdi
    109f:       73 07                   jae    10a8 <main+0x40>
    10a1:       48 39 f7                cmp    %rsi,%rdi
    10a4:       76 02                   jbe    10a8 <main+0x40>
    10a6:       0f 0b                   ud2    
    10a8:       ba 04 00 00 00          mov    $0x4,%edx
    10ad:       e8 6e ff ff ff          callq  1020 <memcpy@plt>
    10b2:       8b 44 24 14             mov    0x14(%rsp),%eax
    10b6:       48 8b 4c 24 18          mov    0x18(%rsp),%rcx
    10bb:       64 48 33 0c 25 28 00    xor    %fs:0x28,%rcx
    10c2:       00 00 
    10c4:       74 05                   je     10cb <main+0x63>
    10c6:       e8 65 ff ff ff          callq  1030 <__stack_chk_fail@plt>
    10cb:       48 83 c4 28             add    $0x28,%rsp
    10cf:       c3                      retq   

Now when compiled with "gcc -U_FORTIFY_SOURCE -Os -fomit-frame-pointer":

0000000000001048 <main>:
    1048:       89 f8                   mov    %edi,%eax
    104a:       c3                      retq   


-O2, -O3 make no difference of course.

Is this considered acceptable? What is the point of such bounds checking?

The example is quite realistic actually, there are tons of code that use
memcpy(&same_type_struct1, &same_type_struct0, sizeof(same_type_struct1))
in critical paths instead of copy assignments.

Or compressors that depend heavily on efficient memcpy within buffer with
pre-verified boundaries. E.g. commenting out just fortify/string.h:memcpy
and rebuilding lz4 gives 10x decompression speed-up (or merely restores
the designed performance).

Nothing like this happens with glibc implementation of _FORTIFY_HEADERS=2.



---
Unsubscribe:  alpine-devel+unsubscribe@lists.alpinelinux.org
Help:         alpine-devel+help@lists.alpinelinux.org
---
A. Wilcox
Details
Message ID
<1E8EE98E-FBEC-460A-AD48-A9EB1BA0CFA9@adelielinux.org>
In-Reply-To
<1394950117.20190225162429@mobile-stream.com> (view parent)
Sender timestamp
1551115612
DKIM signature
missing
Download raw message
On Feb 25, 2019, at 7:24 AM, alpine-mips-patches <info@mobile-stream.com> wrote:
> 
> (this e-mail is a resend triggered by the aports commit 228579f6c7663dc4107b1b418367e968513277f9)
> 
> This is some dumb program:
> 
> #include <string.h>
> int main(int argc, char **argv)
> {
>        int x;
>        memcpy(&x, &argc, sizeof x);
>        return x;
> }
> 
> This is what it turns into when compiled with "gcc -Os -fomit-frame-pointer" on edge (or 3.8.1):
> 
> 0000000000001068 <main>:
>    1068:       48 83 ec 28             sub    $0x28,%rsp
>    106c:       89 7c 24 0c             mov    %edi,0xc(%rsp)
>    1070:       48 8d 7c 24 14          lea    0x14(%rsp),%rdi
>    1075:       48 8d 74 24 0c          lea    0xc(%rsp),%rsi
>    107a:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
>    1081:       00 00 
>    1083:       48 89 44 24 18          mov    %rax,0x18(%rsp)
>    1088:       31 c0                   xor    %eax,%eax
>    108a:       48 8d 47 04             lea    0x4(%rdi),%rax
>    108e:       48 39 c6                cmp    %rax,%rsi
>    1091:       73 05                   jae    1098 <main+0x30>
>    1093:       48 39 f7                cmp    %rsi,%rdi
>    1096:       72 0e                   jb     10a6 <main+0x3e>
>    1098:       48 8d 46 04             lea    0x4(%rsi),%rax
>    109c:       48 39 c7                cmp    %rax,%rdi
>    109f:       73 07                   jae    10a8 <main+0x40>
>    10a1:       48 39 f7                cmp    %rsi,%rdi
>    10a4:       76 02                   jbe    10a8 <main+0x40>
>    10a6:       0f 0b                   ud2    
>    10a8:       ba 04 00 00 00          mov    $0x4,%edx
>    10ad:       e8 6e ff ff ff          callq  1020 <memcpy@plt>
>    10b2:       8b 44 24 14             mov    0x14(%rsp),%eax
>    10b6:       48 8b 4c 24 18          mov    0x18(%rsp),%rcx
>    10bb:       64 48 33 0c 25 28 00    xor    %fs:0x28,%rcx
>    10c2:       00 00 
>    10c4:       74 05                   je     10cb <main+0x63>
>    10c6:       e8 65 ff ff ff          callq  1030 <__stack_chk_fail@plt>
>    10cb:       48 83 c4 28             add    $0x28,%rsp
>    10cf:       c3                      retq   
> 
> Now when compiled with "gcc -U_FORTIFY_SOURCE -Os -fomit-frame-pointer":
> 
> 0000000000001048 <main>:
>    1048:       89 f8                   mov    %edi,%eax
>    104a:       c3                      retq   
> 
> 
> -O2, -O3 make no difference of course.
> 
> Is this considered acceptable? What is the point of such bounds checking?
> 
> The example is quite realistic actually, there are tons of code that use
> memcpy(&same_type_struct1, &same_type_struct0, sizeof(same_type_struct1))
> in critical paths instead of copy assignments.
> 
> Or compressors that depend heavily on efficient memcpy within buffer with
> pre-verified boundaries. E.g. commenting out just fortify/string.h:memcpy
> and rebuilding lz4 gives 10x decompression speed-up (or merely restores
> the designed performance).
> 
> Nothing like this happens with glibc implementation of _FORTIFY_HEADERS=2.


FWIW, we (Adélie) dropped fortify-headers entirely. GCC has gotten good enough at detecting egregious errors and warn/error on them. It not only causes slow downs but over a dozen compilation errors in our package tree.

--
A. Wilcox (Sent from my iPhone - not signed)
Project Lead, Adélie Linux
https://www.adelielinux.org