On Tue, Dec 06, 2022 at 11:13:38AM +0100, Vitaly Zaitsev via devel wrote: > On 05/12/2022 20:58, Ben Cotton wrote: > > Replace the current `_FORTIFY_SOURCE=2` with `_FORTIFY_SOURCE=3` to > > improve mitigation of security issues arising from buffer overflows in > > packages in Fedora. > > AFAIK, _FORTIFY_SOURCE=3 enables runtime checks for every mem*() function > call. This should result in significant performance degradation. That is misunderstanding. The way _FORTIFY_SOURCE works is that say for memcpy if the destination has known upper bound on size (__builtin_object_size (dst, 0) returns something other than ~(size_t)0), then __memcpy_chk is used instead of memcpy, unless the compiler can prove that the length will always fit into that destination (in that case it is folded back to (builtin) memcpy). So, "every" is definitely not the case. In many cases nothing is known about the size of the destination, and in a lot of cases it is provable that no overflow will happen. #define _FORTIFY_SOURCE 2 // or 3 #include <string.h> void qux (void *); void foo (void *dst, void *src, size_t len) { memcpy (dst, src, len); } // Nothing is known about the length of dst above, so it will be normal memcpy void bar (void *src) { char dst[64]; memcpy (dst, src, 32); qux (dst); } // __builtin_object_size (dst, 0) is 64, but 32 <= 64, so again it will be // normal memcpy. void baz (void *src, size_t len) { char dst[64]; memcpy (dst, src, len); qux (dst); } // __builtin_object_size (dst, 0) is 64, we don't know if len <= 64, so // with _FORTIFY_SOURCE 1 and higher there will be __memcpy_chk (dst, src, len, 64); // call. The only change that happens between _FORTIFY_SOURCE 2 and 3 is that in the former case only constant upper bounds are computed, while __builtin_dynamic_object_size can compute either constant (including ~(size_t) 0 for don't know, no upper bound) or something computed at runtime. void quux (void *src, size_t len) { char dst = malloc (64); memcpy (dst, src, len); qux (dst); } // The above will still have even with _FORTIFY_SOURCE 2 __bos0 (dst) 64, so // again __memcpy_chk (dst, src, len, 64); void corge (void *src, size_t sz, size_t len) { char dst = malloc (sz); memcpy (dst, src, len); qux (dst); } // But the above case changes with -D_FORTIFY_SOURCE=3, with 2 __bos0 (dst) // is -1, with 3 __bdos0 (dst) is sz. In this case it is still quite cheap // to compute, just means extending the lifetime of sz until the // __memcpy_chk (dst, src, len, sz); call. True, in some other cases it // might be more expensive to compute, but the goal is still that the // compiler can punt at any time to -1 if the computation of the length // would be too expensive. > To proposal owner: add information about potential performance degradation, > including benchmark results. Deferring that to Siddhesh, I haven't done that benchmarking myself. Jakub _______________________________________________ devel mailing list -- devel@xxxxxxxxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxxxxxxxx Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/devel@xxxxxxxxxxxxxxxxxxxxxxx Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue