Skip to content

Conversation

thomasnyman
Copy link
Contributor

@thomasnyman thomasnyman commented Sep 19, 2024

  • Move -D_FORTIFY_SOURCE optimization level requirement to the description in the detailed section table
  • Reorder -D_FORTIFY_SOURCE variants in the detailed section table to be consistent with the ordering of other options
  • Add additional information to "additional considerations" on how optimization levels affect -D_FORTIFY_SOURCE performance

This makes the -D_FORTIFY_SOURCE table in the detailed section consistent with the recommended option table.

Signed-off-by: Thomas Nyman <[email protected]>
This makes the -D_FORTIFY_SOURCE table in the detailed section consistent with how other options have their variants ordered.

Signed-off-by: Thomas Nyman <[email protected]>
@thomasnyman thomasnyman changed the title clarify_fortify_source_opt_levels Clarify -D_FORTIFY_SOURCE interaction with optimization levels Sep 19, 2024
@thomasnyman thomasnyman merged commit cd2cb52 into main Sep 19, 2024
5 checks passed
@thomasnyman thomasnyman deleted the clarify_fortify_source_opt_levels branch September 19, 2024 13:37
Copy link
Contributor

@siddhesh siddhesh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I think I 'reviewed' this a bit too late, putting my comments in nevertheless, hopefully they're helpful.

#### Additional Considerations

- Applications that incorrectly use `malloc_usable_size`[^malloc_usable_size] to use the additional size reported by the function may abort at runtime. This is a bug in the application because the additional size reported by `malloc_usable_size` is not generally safe to dereference and is for diagnostic uses only. The correct fix for such issues is to avoid using `malloc_usable_size` as the glibc manual specifically states that it is for diagnostic purposes *only* [^malloc_usable_size]. On many Linux systems these incorrect uses can be detected by running `readelf -Ws <path>` on the ELF binaries and searching for `malloc_usable_size@GLIBC`[^kpyrd23]. If avoiding `malloc_usable_size` is not possible, one may call `realloc` to resize the block to its usable size and to benefit from `_FORTIFY_SOURCE=3`.
Internally `-D_FORTIFY_SOURCE` relies on the built-in functions for object size checking in GCC[^gcc-objectsizechecks] and Clang[^clang-evaluatingobjectsize], namely `__builtin_object_size` and `__builtin_dynamic_object_size`. These builtins provide conservative approximations of the object size and are sensitive to compiler optimizations. With optimization enabled they produce more accurate estimates, especially when a call to `__builtin_object_size` is in a different function from where its argument pointer is formed. In addition, GCC allows more information about subobject bounds to be determined with higher optimization levels. Hence we recommending enabling `-D_FORTIFY_SOURCE=3` with at least optimization level `-O2`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't call out the subobject bounds so prominently because in practice better optimization can also sometimes result in subobject information being lost. I think a more reliable claim would be that higher optimization allows more number of __builtin_object_size and __builtin_dynamic_object_size calls to succeed, not the accuracy of their size estimates.

- Applications that incorrectly use `malloc_usable_size`[^malloc_usable_size] to use the additional size reported by the function may abort at runtime. This is a bug in the application because the additional size reported by `malloc_usable_size` is not generally safe to dereference and is for diagnostic uses only. The correct fix for such issues is to avoid using `malloc_usable_size` as the glibc manual specifically states that it is for diagnostic purposes *only* [^malloc_usable_size]. On many Linux systems these incorrect uses can be detected by running `readelf -Ws <path>` on the ELF binaries and searching for `malloc_usable_size@GLIBC`[^kpyrd23]. If avoiding `malloc_usable_size` is not possible, one may call `realloc` to resize the block to its usable size and to benefit from `_FORTIFY_SOURCE=3`.
Internally `-D_FORTIFY_SOURCE` relies on the built-in functions for object size checking in GCC[^gcc-objectsizechecks] and Clang[^clang-evaluatingobjectsize], namely `__builtin_object_size` and `__builtin_dynamic_object_size`. These builtins provide conservative approximations of the object size and are sensitive to compiler optimizations. With optimization enabled they produce more accurate estimates, especially when a call to `__builtin_object_size` is in a different function from where its argument pointer is formed. In addition, GCC allows more information about subobject bounds to be determined with higher optimization levels. Hence we recommending enabling `-D_FORTIFY_SOURCE=3` with at least optimization level `-O2`.

Applications that incorrectly use `malloc_usable_size`[^malloc_usable_size] to use the additional size reported by the function may abort at runtime. This is a bug in the application because the additional size reported by `malloc_usable_size` is not generally safe to dereference and is for diagnostic uses only. The correct fix for such issues is to avoid using `malloc_usable_size` as the glibc manual specifically states that it is for diagnostic purposes *only* [^malloc_usable_size]. On many Linux systems these incorrect uses can be detected by running `readelf -Ws <path>` on the ELF binaries and searching for `malloc_usable_size@GLIBC`[^kpyrd23]. If avoiding `malloc_usable_size` is not possible, one may call `realloc` to resize the block to its usable size and to benefit from `_FORTIFY_SOURCE=3`.
Copy link
Contributor

@siddhesh siddhesh Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

systemd for example uses a dummy realloc hack to fool the compiler into thinking that the larger block is available, but I don't know if it's a good idea to recommend such practice:

https://github.com/systemd/systemd/blob/main/src/basic/alloc-util.h#L192

Also, I had introduced a fast path in realloc in glibc-2.37 that makes such hacks unnecessary since the glibc realloc should return the same block immediately if the new size fits into it. That may or may not be true for alternate allocators though.

Copy link
Contributor

@thesamesam thesamesam Sep 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're in the business of telling people what best practice is, we should indeed actively tell them not to do that at all. The only reason we haven't completely killed it in glibc is because we can't quite agree on how to move forward, but everyone accepts that using it like this is bad.

(I haven't brought it up again given that I haven't hit any other instances.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants