(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
---
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