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@lists.fedoraproject.org
To unsubscribe send an email to devel-le...@lists.fedoraproject.org
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@lists.fedoraproject.org
Do not reply to spam, report it: 
https://pagure.io/fedora-infrastructure/new_issue

Reply via email to